diff options
841 files changed, 17847 insertions, 11878 deletions
diff --git a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java index 53a388913118..c572f82ac1d9 100644 --- a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java +++ b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java @@ -32,8 +32,6 @@ import android.annotation.SystemService; import android.annotation.UserHandleAware; import android.content.Context; -import com.android.internal.util.FrameworkStatsLog; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Collections; @@ -453,62 +451,6 @@ public class PowerExemptionManager { @Retention(RetentionPolicy.SOURCE) public @interface ReasonCode {} - private static final int EXEMPTION_REASON_SYSTEM_UID = FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_SYSTEM_UID; - private static final int EXEMPTION_REASON_ALLOWLISTED_PACKAGE = FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_ALLOWLISTED_PACKAGE; - private static final int EXEMPTION_REASON_COMPANION_DEVICE_MANAGER = FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_COMPANION_DEVICE_MANAGER; - private static final int EXEMPTION_REASON_DEVICE_DEMO_MODE = FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_DEVICE_DEMO_MODE; - private static final int EXEMPTION_REASON_DEVICE_OWNER = FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_DEVICE_OWNER; - private static final int EXEMPTION_REASON_PROFILE_OWNER = FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_PROFILE_OWNER; - private static final int EXEMPTION_REASON_PROC_STATE_PERSISTENT = FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_PROC_STATE_PERSISTENT; - private static final int EXEMPTION_REASON_PROC_STATE_PERSISTENT_UI = FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_PROC_STATE_PERSISTENT_UI; - private static final int EXEMPTION_REASON_OP_ACTIVATE_VPN = FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_OP_ACTIVATE_VPN; - private static final int EXEMPTION_REASON_OP_ACTIVATE_PLATFORM_VPN = FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_OP_ACTIVATE_PLATFORM_VPN; - private static final int EXEMPTION_REASON_SYSTEM_MODULE = FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_SYSTEM_MODULE; - private static final int EXEMPTION_REASON_CARRIER_PRIVILEGED_APP = FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_CARRIER_PRIVILEGED_APP; - private static final int EXEMPTION_REASON_SYSTEM_ALLOW_LISTED = FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_SYSTEM_ALLOW_LISTED; - private static final int EXEMPTION_REASON_ROLE_DIALER = FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_ROLE_DIALER; - private static final int EXEMPTION_REASON_ROLE_EMERGENCY = FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_ROLE_EMERGENCY; - private static final int EXEMPTION_REASON_DENIED = FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_DENIED; - /** - * List of exemption reason codes used for statsd logging in AppBackgroundRestrictionsInfo atom. - * @hide - */ - @IntDef(prefix = { "EXEMPTION_REASON_" }, value = { - EXEMPTION_REASON_SYSTEM_UID, - EXEMPTION_REASON_ALLOWLISTED_PACKAGE, - EXEMPTION_REASON_COMPANION_DEVICE_MANAGER, - EXEMPTION_REASON_DEVICE_DEMO_MODE, - EXEMPTION_REASON_DEVICE_OWNER, - EXEMPTION_REASON_PROFILE_OWNER, - EXEMPTION_REASON_PROC_STATE_PERSISTENT, - EXEMPTION_REASON_PROC_STATE_PERSISTENT_UI, - EXEMPTION_REASON_OP_ACTIVATE_VPN, - EXEMPTION_REASON_OP_ACTIVATE_PLATFORM_VPN, - EXEMPTION_REASON_SYSTEM_MODULE, - EXEMPTION_REASON_CARRIER_PRIVILEGED_APP, - EXEMPTION_REASON_SYSTEM_ALLOW_LISTED, - EXEMPTION_REASON_ROLE_DIALER, - EXEMPTION_REASON_ROLE_EMERGENCY, - EXEMPTION_REASON_DENIED, - }) - public @interface ExemptionReason {} - /** * @hide */ @@ -679,40 +621,40 @@ public class PowerExemptionManager { * @hide * @return the reason code mapped to statsd for the AppBackgroundRestrictionsInfo atom. */ - public static @ExemptionReason int getExemptionReasonForStatsd(@ReasonCode int reasonCode) { + public static int getExemptionReasonForStatsd(@ReasonCode int reasonCode) { switch (reasonCode) { case REASON_SYSTEM_UID: - return EXEMPTION_REASON_SYSTEM_UID; + return AppBackgroundRestrictionsInfo.REASON_SYSTEM_UID; case REASON_ALLOWLISTED_PACKAGE: - return EXEMPTION_REASON_ALLOWLISTED_PACKAGE; + return AppBackgroundRestrictionsInfo.REASON_ALLOWLISTED_PACKAGE; case REASON_COMPANION_DEVICE_MANAGER: - return EXEMPTION_REASON_COMPANION_DEVICE_MANAGER; + return AppBackgroundRestrictionsInfo.REASON_COMPANION_DEVICE_MANAGER; case REASON_DEVICE_DEMO_MODE: - return EXEMPTION_REASON_DEVICE_DEMO_MODE; + return AppBackgroundRestrictionsInfo.REASON_DEVICE_DEMO_MODE; case REASON_DEVICE_OWNER: - return EXEMPTION_REASON_DEVICE_OWNER; + return AppBackgroundRestrictionsInfo.REASON_DEVICE_OWNER; case REASON_PROFILE_OWNER: - return EXEMPTION_REASON_PROFILE_OWNER; + return AppBackgroundRestrictionsInfo.REASON_PROFILE_OWNER; case REASON_PROC_STATE_PERSISTENT: - return EXEMPTION_REASON_PROC_STATE_PERSISTENT; + return AppBackgroundRestrictionsInfo.REASON_PROC_STATE_PERSISTENT; case REASON_PROC_STATE_PERSISTENT_UI: - return EXEMPTION_REASON_PROC_STATE_PERSISTENT_UI; + return AppBackgroundRestrictionsInfo.REASON_PROC_STATE_PERSISTENT_UI; case REASON_OP_ACTIVATE_VPN: - return EXEMPTION_REASON_OP_ACTIVATE_VPN; + return AppBackgroundRestrictionsInfo.REASON_OP_ACTIVATE_VPN; case REASON_OP_ACTIVATE_PLATFORM_VPN: - return EXEMPTION_REASON_OP_ACTIVATE_PLATFORM_VPN; + return AppBackgroundRestrictionsInfo.REASON_OP_ACTIVATE_PLATFORM_VPN; case REASON_SYSTEM_MODULE: - return EXEMPTION_REASON_SYSTEM_MODULE; + return AppBackgroundRestrictionsInfo.REASON_SYSTEM_MODULE; case REASON_CARRIER_PRIVILEGED_APP: - return EXEMPTION_REASON_CARRIER_PRIVILEGED_APP; + return AppBackgroundRestrictionsInfo.REASON_CARRIER_PRIVILEGED_APP; case REASON_SYSTEM_ALLOW_LISTED: - return EXEMPTION_REASON_SYSTEM_ALLOW_LISTED; + return AppBackgroundRestrictionsInfo.REASON_SYSTEM_ALLOW_LISTED; case REASON_ROLE_DIALER: - return EXEMPTION_REASON_ROLE_DIALER; + return AppBackgroundRestrictionsInfo.REASON_ROLE_DIALER; case REASON_ROLE_EMERGENCY: - return EXEMPTION_REASON_ROLE_EMERGENCY; + return AppBackgroundRestrictionsInfo.REASON_ROLE_EMERGENCY; default: - return EXEMPTION_REASON_DENIED; + return AppBackgroundRestrictionsInfo.REASON_DENIED; } } diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java index 881453fe237d..0e4887d27b53 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java @@ -612,8 +612,7 @@ public class AlarmManagerService extends SystemService { private static final boolean DEFAULT_KILL_ON_SCHEDULE_EXACT_ALARM_REVOKED = true; - // TODO(b/226439802): Flip to true. - private static final boolean DEFAULT_SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT = false; + private static final boolean DEFAULT_SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT = true; // Minimum futurity of a new alarm public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY; diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java index 25db58ed6261..9e131339595f 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java @@ -1387,6 +1387,7 @@ public class JobSchedulerService extends com.android.server.SystemService if (mPendingJobQueue.remove(cancelled)) { mJobPackageTracker.noteNonpending(cancelled); } + mChangedJobList.remove(cancelled); // Cancel if running. mConcurrencyManager.stopJobOnServiceContextLocked( cancelled, reason, internalReasonCode, debugReason); @@ -1894,11 +1895,14 @@ public class JobSchedulerService extends com.android.server.SystemService // The job ran past its expected run window. Have it count towards the current window // and schedule a new job for the next window. if (DEBUG) { - Slog.i(TAG, "Periodic job ran after its intended window."); + Slog.i(TAG, "Periodic job ran after its intended window by " + diffMs + " ms"); } long numSkippedWindows = (diffMs / period) + 1; // +1 to include original window - if (period != flex && diffMs > Math.min(PERIODIC_JOB_WINDOW_BUFFER, - (period - flex) / 2)) { + // Determine how far into a single period the job ran, and determine if it's too close + // to the start of the next period. If the difference between the start of the execution + // window and the previous execution time inside of the period is less than the + // threshold, then we say that the job ran too close to the next period. + if (period != flex && (period - flex - (diffMs % period)) <= flex / 6) { if (DEBUG) { Slog.d(TAG, "Custom flex job ran too close to next window."); } diff --git a/api/api.go b/api/api.go index 94bccaaa8250..9aac879b4eae 100644 --- a/api/api.go +++ b/api/api.go @@ -27,6 +27,7 @@ import ( const art = "art.module.public.api" const conscrypt = "conscrypt.module.public.api" const i18n = "i18n.module.public.api" + var core_libraries_modules = []string{art, conscrypt, i18n} // The intention behind this soong plugin is to generate a number of "merged" @@ -92,6 +93,8 @@ type fgProps struct { type MergedTxtDefinition struct { // "current.txt" or "removed.txt" TxtFilename string + // Filename in the new dist dir. "android.txt" or "android-removed.txt" + DistFilename string // The module for the non-updatable / non-module part of the api. BaseTxt string // The list of modules that are relevant for this merged txt. @@ -112,7 +115,6 @@ func createMergedTxt(ctx android.LoadHookContext, txt MergedTxtDefinition) { if txt.Scope != "public" { filename = txt.Scope + "-" + filename } - props := genruleProps{} props.Name = proptools.StringPtr(ctx.ModuleName() + "-" + filename) props.Tools = []string{"metalava"} @@ -126,9 +128,9 @@ func createMergedTxt(ctx android.LoadHookContext, txt MergedTxtDefinition) { Dest: proptools.StringPtr(filename), }, { - Targets: []string{"sdk"}, + Targets: []string{"api_txt", "sdk"}, Dir: proptools.StringPtr("apistubs/android/" + txt.Scope + "/api"), - Dest: proptools.StringPtr(txt.TxtFilename), + Dest: proptools.StringPtr(txt.DistFilename), }, } props.Visibility = []string{"//visibility:public"} @@ -240,34 +242,39 @@ func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_ var textFiles []MergedTxtDefinition tagSuffix := []string{".api.txt}", ".removed-api.txt}"} + distFilename := []string{"android.txt", "android-removed.txt"} for i, f := range []string{"current.txt", "removed.txt"} { textFiles = append(textFiles, MergedTxtDefinition{ - TxtFilename: f, - BaseTxt: ":non-updatable-" + f, - Modules: bootclasspath, - ModuleTag: "{.public" + tagSuffix[i], - Scope: "public", + TxtFilename: f, + DistFilename: distFilename[i], + BaseTxt: ":non-updatable-" + f, + Modules: bootclasspath, + ModuleTag: "{.public" + tagSuffix[i], + Scope: "public", }) textFiles = append(textFiles, MergedTxtDefinition{ - TxtFilename: f, - BaseTxt: ":non-updatable-system-" + f, - Modules: bootclasspath, - ModuleTag: "{.system" + tagSuffix[i], - Scope: "system", + TxtFilename: f, + DistFilename: distFilename[i], + BaseTxt: ":non-updatable-system-" + f, + Modules: bootclasspath, + ModuleTag: "{.system" + tagSuffix[i], + Scope: "system", }) textFiles = append(textFiles, MergedTxtDefinition{ - TxtFilename: f, - BaseTxt: ":non-updatable-module-lib-" + f, - Modules: bootclasspath, - ModuleTag: "{.module-lib" + tagSuffix[i], - Scope: "module-lib", + TxtFilename: f, + DistFilename: distFilename[i], + BaseTxt: ":non-updatable-module-lib-" + f, + Modules: bootclasspath, + ModuleTag: "{.module-lib" + tagSuffix[i], + Scope: "module-lib", }) textFiles = append(textFiles, MergedTxtDefinition{ - TxtFilename: f, - BaseTxt: ":non-updatable-system-server-" + f, - Modules: system_server_classpath, - ModuleTag: "{.system-server" + tagSuffix[i], - Scope: "system-server", + TxtFilename: f, + DistFilename: distFilename[i], + BaseTxt: ":non-updatable-system-server-" + f, + Modules: system_server_classpath, + ModuleTag: "{.system-server" + tagSuffix[i], + Scope: "system-server", }) } for _, txt := range textFiles { diff --git a/cmds/telecom/src/com/android/commands/telecom/Telecom.java b/cmds/telecom/src/com/android/commands/telecom/Telecom.java index 52f883b5fbb7..d464e266ac36 100644 --- a/cmds/telecom/src/com/android/commands/telecom/Telecom.java +++ b/cmds/telecom/src/com/android/commands/telecom/Telecom.java @@ -37,6 +37,8 @@ import com.android.internal.os.BaseCommand; import com.android.internal.telecom.ITelecomService; import java.io.PrintStream; +import java.util.Arrays; +import java.util.stream.Collectors; public final class Telecom extends BaseCommand { @@ -90,6 +92,10 @@ public final class Telecom extends BaseCommand { private static final String COMMAND_GET_MAX_PHONES = "get-max-phones"; private static final String COMMAND_SET_TEST_EMERGENCY_PHONE_ACCOUNT_PACKAGE_FILTER = "set-test-emergency-phone-account-package-filter"; + /** + * Command used to emit a distinct "mark" in the logs. + */ + private static final String COMMAND_LOG_MARK = "log-mark"; private ComponentName mComponent; private String mAccountId; @@ -161,6 +167,8 @@ public final class Telecom extends BaseCommand { + " package name that will be used for test emergency calls. To clear," + " send an empty package name. Real emergency calls will still be placed" + " over Telephony.\n" + + "telecom log-mark <MESSAGE>: emits a message into the telecom logs. Useful for " + + "testers to indicate where in the logs various test steps take place.\n" ); } @@ -265,6 +273,9 @@ public final class Telecom extends BaseCommand { case COMMAND_SET_TEST_EMERGENCY_PHONE_ACCOUNT_PACKAGE_FILTER: runSetEmergencyPhoneAccountPackageFilter(); break; + case COMMAND_LOG_MARK: + runLogMark(); + break; default: Log.w(this, "onRun: unknown command: %s", command); throw new IllegalArgumentException ("unknown command '" + command + "'"); @@ -442,6 +453,11 @@ public final class Telecom extends BaseCommand { } + private void runLogMark() throws RemoteException { + String message = Arrays.stream(mArgs.peekRemainingArgs()).collect(Collectors.joining(" ")); + mTelecomService.requestLogMark(message); + } + private PhoneAccountHandle getPhoneAccountHandleFromArgs() throws RemoteException { if (TextUtils.isEmpty(mArgs.peekNextArg())) { return null; diff --git a/core/api/current.txt b/core/api/current.txt index b08ffc90a00d..e260ad046918 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -335,15 +335,15 @@ package android { field public static final int allowClearUserData = 16842757; // 0x1010005 field public static final int allowClickWhenDisabled = 16844312; // 0x1010618 field public static final int allowEmbedded = 16843765; // 0x10103f5 - field public static final int allowGameAngleDriver; - field public static final int allowGameDownscaling; - field public static final int allowGameFpsOverride; + field public static final int allowGameAngleDriver = 16844376; // 0x1010658 + field public static final int allowGameDownscaling = 16844377; // 0x1010659 + field public static final int allowGameFpsOverride = 16844378; // 0x101065a field public static final int allowNativeHeapPointerTagging = 16844306; // 0x1010612 field public static final int allowParallelSyncs = 16843570; // 0x1010332 field public static final int allowSingleTap = 16843353; // 0x1010259 field public static final int allowTaskReparenting = 16843268; // 0x1010204 field public static final int allowUndo = 16843999; // 0x10104df - field public static final int allowUntrustedActivityEmbedding; + field public static final int allowUntrustedActivityEmbedding = 16844393; // 0x1010669 field public static final int alpha = 16843551; // 0x101031f field public static final int alphabeticModifiers = 16844110; // 0x101054e field public static final int alphabeticShortcut = 16843235; // 0x10101e3 @@ -374,7 +374,7 @@ package android { field public static final int authorities = 16842776; // 0x1010018 field public static final int autoAdvanceViewId = 16843535; // 0x101030f field public static final int autoCompleteTextViewStyle = 16842859; // 0x101006b - field public static final int autoHandwritingEnabled; + field public static final int autoHandwritingEnabled = 16844382; // 0x101065e field public static final int autoLink = 16842928; // 0x10100b0 field public static final int autoMirrored = 16843754; // 0x10103ea field public static final int autoRemoveFromRecents = 16843847; // 0x1010447 @@ -390,7 +390,7 @@ package android { field public static final int autoVerify = 16844014; // 0x10104ee field public static final int autofillHints = 16844118; // 0x1010556 field public static final int autofilledHighlight = 16844136; // 0x1010568 - field public static final int backdropColor; + field public static final int backdropColor = 16844402; // 0x1010672 field public static final int background = 16842964; // 0x10100d4 field public static final int backgroundDimAmount = 16842802; // 0x1010032 field public static final int backgroundDimEnabled = 16843295; // 0x101021f @@ -437,7 +437,7 @@ package android { field public static final int calendarViewShown = 16843596; // 0x101034c field public static final int calendarViewStyle = 16843613; // 0x101035d field public static final int canControlMagnification = 16844039; // 0x1010507 - field public static final int canDisplayOnRemoteDevices; + field public static final int canDisplayOnRemoteDevices = 16844368; // 0x1010650 field public static final int canPauseRecording = 16844314; // 0x101061a field public static final int canPerformGestures = 16844045; // 0x101050d field public static final int canRecord = 16844060; // 0x101051c @@ -632,7 +632,7 @@ package android { field public static final int elevation = 16843840; // 0x1010440 field public static final int ellipsize = 16842923; // 0x10100ab field public static final int ems = 16843096; // 0x1010158 - field public static final int enableOnBackInvokedCallback; + field public static final int enableOnBackInvokedCallback = 16844396; // 0x101066c field public static final int enableVrMode = 16844069; // 0x1010525 field public static final int enabled = 16842766; // 0x101000e field public static final int end = 16843996; // 0x10104dc @@ -744,10 +744,10 @@ package android { field public static final int freezesText = 16843116; // 0x101016c field public static final int fromAlpha = 16843210; // 0x10101ca field public static final int fromDegrees = 16843187; // 0x10101b3 - field public static final int fromExtendBottom; - field public static final int fromExtendLeft; - field public static final int fromExtendRight; - field public static final int fromExtendTop; + field public static final int fromExtendBottom = 16844386; // 0x1010662 + field public static final int fromExtendLeft = 16844383; // 0x101065f + field public static final int fromExtendRight = 16844385; // 0x1010661 + field public static final int fromExtendTop = 16844384; // 0x1010660 field public static final int fromId = 16843850; // 0x101044a field public static final int fromScene = 16843741; // 0x10103dd field public static final int fromXDelta = 16843206; // 0x10101c6 @@ -867,7 +867,7 @@ package android { field public static final int installLocation = 16843447; // 0x10102b7 field public static final int interactiveUiTimeout = 16844181; // 0x1010595 field public static final int interpolator = 16843073; // 0x1010141 - field public static final int intro; + field public static final int intro = 16844395; // 0x101066b field public static final int isAccessibilityTool = 16844353; // 0x1010641 field public static final int isAlwaysSyncable = 16843571; // 0x1010333 field public static final int isAsciiCapable = 16843753; // 0x10103e9 @@ -910,7 +910,7 @@ package android { field public static final int keyboardNavigationCluster = 16844096; // 0x1010540 field public static final int keycode = 16842949; // 0x10100c5 field public static final int killAfterRestore = 16843420; // 0x101029c - field public static final int knownActivityEmbeddingCerts; + field public static final int knownActivityEmbeddingCerts = 16844394; // 0x101066a field public static final int knownCerts = 16844330; // 0x101062a field public static final int lStar = 16844359; // 0x1010647 field public static final int label = 16842753; // 0x1010001 @@ -978,8 +978,8 @@ package android { field public static final int left = 16843181; // 0x10101ad field public static final int letterSpacing = 16843958; // 0x10104b6 field public static final int level = 16844032; // 0x1010500 - field public static final int lineBreakStyle; - field public static final int lineBreakWordStyle; + field public static final int lineBreakStyle = 16844398; // 0x101066e + field public static final int lineBreakWordStyle = 16844399; // 0x101066f field public static final int lineHeight = 16844159; // 0x101057f field public static final int lineSpacingExtra = 16843287; // 0x1010217 field public static final int lineSpacingMultiplier = 16843288; // 0x1010218 @@ -1003,7 +1003,7 @@ package android { field public static final int listSeparatorTextViewStyle = 16843272; // 0x1010208 field public static final int listViewStyle = 16842868; // 0x1010074 field public static final int listViewWhiteStyle = 16842869; // 0x1010075 - field public static final int localeConfig; + field public static final int localeConfig = 16844379; // 0x101065b field public static final int lockTaskMode = 16844013; // 0x10104ed field public static final int logo = 16843454; // 0x10102be field public static final int logoDescription = 16844009; // 0x10104e9 @@ -1162,7 +1162,7 @@ package android { field public static final int popupWindowStyle = 16842870; // 0x1010076 field public static final int port = 16842793; // 0x1010029 field public static final int positiveButtonText = 16843253; // 0x10101f5 - field public static final int preferKeepClear; + field public static final int preferKeepClear = 16844381; // 0x101065d field public static final int preferMinimalPostProcessing = 16844300; // 0x101060c field public static final int preferenceCategoryStyle = 16842892; // 0x101008c field public static final int preferenceFragmentStyle = 16844038; // 0x1010506 @@ -1238,10 +1238,10 @@ package android { field public static final int requiredFeature = 16844116; // 0x1010554 field public static final int requiredForAllUsers = 16843728; // 0x10103d0 field public static final int requiredNotFeature = 16844117; // 0x1010555 - field public static final int requiredSplitTypes; + field public static final int requiredSplitTypes = 16844366; // 0x101064e field public static final int requiresFadingEdge = 16843685; // 0x10103a5 field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364 - field public static final int resetEnabledSettingsOnAppDataCleared; + field public static final int resetEnabledSettingsOnAppDataCleared = 16844370; // 0x1010652 field public static final int resizeClip = 16843983; // 0x10104cf field public static final int resizeMode = 16843619; // 0x1010363 field public static final int resizeable = 16843405; // 0x101028d @@ -1337,7 +1337,7 @@ package android { field public static final int shareInterpolator = 16843195; // 0x10101bb field @Deprecated public static final int sharedUserId = 16842763; // 0x101000b field @Deprecated public static final int sharedUserLabel = 16843361; // 0x1010261 - field public static final int sharedUserMaxSdkVersion; + field public static final int sharedUserMaxSdkVersion = 16844365; // 0x101064d field public static final int shell = 16844180; // 0x1010594 field public static final int shortcutDisabledMessage = 16844075; // 0x101052b field public static final int shortcutId = 16844072; // 0x1010528 @@ -1346,8 +1346,8 @@ package android { field public static final int shouldDisableView = 16843246; // 0x10101ee field public static final int shouldUseDefaultUnfoldTransition = 16844364; // 0x101064c field public static final int showAsAction = 16843481; // 0x10102d9 - field public static final int showBackdrop; - field public static final int showClockAndComplications; + field public static final int showBackdrop = 16844380; // 0x101065c + field public static final int showClockAndComplications = 16844372; // 0x1010654 field public static final int showDefault = 16843258; // 0x10101fa field public static final int showDividers = 16843561; // 0x1010329 field public static final int showForAllUsers = 16844015; // 0x10104ef @@ -1378,7 +1378,7 @@ package android { field public static final int splitMotionEvents = 16843503; // 0x10102ef field public static final int splitName = 16844105; // 0x1010549 field public static final int splitTrack = 16843852; // 0x101044c - field public static final int splitTypes; + field public static final int splitTypes = 16844367; // 0x101064f field public static final int spotShadowAlpha = 16843967; // 0x10104bf field public static final int src = 16843033; // 0x1010119 field public static final int ssp = 16843747; // 0x10103e3 @@ -1449,18 +1449,18 @@ package android { field public static final int summaryColumn = 16843426; // 0x10102a2 field public static final int summaryOff = 16843248; // 0x10101f0 field public static final int summaryOn = 16843247; // 0x10101ef - field public static final int supportedTypes; + field public static final int supportedTypes = 16844369; // 0x1010651 field public static final int supportsAssist = 16844016; // 0x10104f0 - field public static final int supportsBatteryGameMode; + field public static final int supportsBatteryGameMode = 16844374; // 0x1010656 field public static final int supportsInlineSuggestions = 16844301; // 0x101060d - field public static final int supportsInlineSuggestionsWithTouchExploration; + field public static final int supportsInlineSuggestionsWithTouchExploration = 16844397; // 0x101066d field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844017; // 0x10104f1 field public static final int supportsLocalInteraction = 16844047; // 0x101050f field public static final int supportsMultipleDisplays = 16844182; // 0x1010596 - field public static final int supportsPerformanceGameMode; + field public static final int supportsPerformanceGameMode = 16844375; // 0x1010657 field public static final int supportsPictureInPicture = 16844023; // 0x10104f7 field public static final int supportsRtl = 16843695; // 0x10103af - field public static final int supportsStylusHandwriting; + field public static final int supportsStylusHandwriting = 16844371; // 0x1010653 field public static final int supportsSwitchingToNextInputMethod = 16843755; // 0x10103eb field public static final int supportsUploading = 16843419; // 0x101029b field public static final int suppressesSpellChecker = 16844355; // 0x1010643 @@ -1579,7 +1579,7 @@ package android { field public static final int tileMode = 16843265; // 0x1010201 field public static final int tileModeX = 16843895; // 0x1010477 field public static final int tileModeY = 16843896; // 0x1010478 - field public static final int tileService; + field public static final int tileService = 16844391; // 0x1010667 field public static final int timePickerDialogTheme = 16843934; // 0x101049e field public static final int timePickerMode = 16843956; // 0x10104b4 field public static final int timePickerStyle = 16843933; // 0x101049d @@ -1598,10 +1598,10 @@ package android { field public static final int titleTextStyle = 16843512; // 0x10102f8 field public static final int toAlpha = 16843211; // 0x10101cb field public static final int toDegrees = 16843188; // 0x10101b4 - field public static final int toExtendBottom; - field public static final int toExtendLeft; - field public static final int toExtendRight; - field public static final int toExtendTop; + field public static final int toExtendBottom = 16844390; // 0x1010666 + field public static final int toExtendLeft = 16844387; // 0x1010663 + field public static final int toExtendRight = 16844389; // 0x1010665 + field public static final int toExtendTop = 16844388; // 0x1010664 field public static final int toId = 16843849; // 0x1010449 field public static final int toScene = 16843742; // 0x10103de field public static final int toXDelta = 16843207; // 0x10101c7 @@ -1753,7 +1753,7 @@ package android { field public static final int windowSplashScreenAnimatedIcon = 16844333; // 0x101062d field @Deprecated public static final int windowSplashScreenAnimationDuration = 16844334; // 0x101062e field public static final int windowSplashScreenBackground = 16844332; // 0x101062c - field public static final int windowSplashScreenBehavior; + field public static final int windowSplashScreenBehavior = 16844392; // 0x1010668 field public static final int windowSplashScreenBrandingImage = 16844335; // 0x101062f field public static final int windowSplashScreenIconBackgroundColor = 16844336; // 0x1010630 field @Deprecated public static final int windowSplashscreenContent = 16844132; // 0x1010564 @@ -2092,7 +2092,7 @@ package android { field public static final int accessibilityActionScrollUp = 16908344; // 0x1020038 field public static final int accessibilityActionSetProgress = 16908349; // 0x102003d field public static final int accessibilityActionShowOnScreen = 16908342; // 0x1020036 - field public static final int accessibilityActionShowTextSuggestions; + field public static final int accessibilityActionShowTextSuggestions = 16908376; // 0x1020058 field public static final int accessibilityActionShowTooltip = 16908356; // 0x1020044 field public static final int accessibilitySystemActionBack = 16908363; // 0x102004b field public static final int accessibilitySystemActionHome = 16908364; // 0x102004c @@ -2128,8 +2128,8 @@ package android { field public static final int icon_frame = 16908350; // 0x102003e field public static final int input = 16908297; // 0x1020009 field public static final int inputArea = 16908318; // 0x102001e - field public static final int inputExtractAccessories; - field public static final int inputExtractAction; + field public static final int inputExtractAccessories = 16908378; // 0x102005a + field public static final int inputExtractAction = 16908377; // 0x1020059 field public static final int inputExtractEditText = 16908325; // 0x1020025 field @Deprecated public static final int keyboardView = 16908326; // 0x1020026 field public static final int list = 16908298; // 0x102000a @@ -2301,7 +2301,7 @@ package android { field public static final int TextAppearance = 16973886; // 0x103003e field public static final int TextAppearance_DeviceDefault = 16974253; // 0x10301ad field public static final int TextAppearance_DeviceDefault_DialogWindowTitle = 16974264; // 0x10301b8 - field public static final int TextAppearance_DeviceDefault_Headline; + field public static final int TextAppearance_DeviceDefault_Headline = 16974565; // 0x10302e5 field public static final int TextAppearance_DeviceDefault_Inverse = 16974254; // 0x10301ae field public static final int TextAppearance_DeviceDefault_Large = 16974255; // 0x10301af field public static final int TextAppearance_DeviceDefault_Large_Inverse = 16974256; // 0x10301b0 @@ -30977,7 +30977,7 @@ package android.os { field public static final int R = 30; // 0x1e field public static final int S = 31; // 0x1f field public static final int S_V2 = 32; // 0x20 - field public static final int TIRAMISU = 10000; // 0x2710 + field public static final int TIRAMISU = 33; // 0x21 } public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable { @@ -52021,7 +52021,6 @@ package android.view.accessibility { method public boolean isSelected(); method @Deprecated public static android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo obtain(int, int, int, int, boolean); method @Deprecated public static android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo obtain(int, int, int, int, boolean, boolean); - method @Deprecated @NonNull public static android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo obtain(@Nullable String, int, int, @Nullable String, int, int, boolean, boolean); } public static final class AccessibilityNodeInfo.CollectionItemInfo.Builder { diff --git a/core/api/removed.txt b/core/api/removed.txt index 608a9a4efeca..1fa1e89fb46e 100644 --- a/core/api/removed.txt +++ b/core/api/removed.txt @@ -525,6 +525,14 @@ package android.view { } +package android.view.accessibility { + + public static final class AccessibilityNodeInfo.CollectionItemInfo { + method @Deprecated @NonNull public static android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo obtain(@Nullable String, int, int, @Nullable String, int, int, boolean, boolean); + } + +} + package android.view.translation { public final class TranslationManager { diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 650de2e00c3b..b25d1e302da5 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -367,12 +367,12 @@ package android { public static final class R.array { field public static final int config_keySystemUuidMapping = 17235973; // 0x1070005 - field public static final int config_optionalIpSecAlgorithms; + field public static final int config_optionalIpSecAlgorithms = 17235974; // 0x1070006 } public static final class R.attr { field public static final int allowClearUserDataOnFailedRestore = 16844288; // 0x1010600 - field public static final int gameSessionService; + field public static final int gameSessionService = 16844373; // 0x1010655 field public static final int hotwordDetectionService = 16844326; // 0x1010626 field public static final int isVrOnly = 16844152; // 0x1010578 field public static final int minExtensionVersion = 16844305; // 0x1010611 @@ -385,7 +385,7 @@ package android { } public static final class R.bool { - field public static final int config_enableQrCodeScannerOnLockScreen; + field public static final int config_enableQrCodeScannerOnLockScreen = 17891336; // 0x1110008 field public static final int config_sendPackageName = 17891328; // 0x1110000 field public static final int config_showDefaultAssistant = 17891329; // 0x1110001 field public static final int config_showDefaultEmergency = 17891330; // 0x1110002 @@ -402,7 +402,7 @@ package android { public static final class R.drawable { field public static final int ic_info = 17301684; // 0x10800b4 - field public static final int ic_safety_protection; + field public static final int ic_safety_protection = 17301685; // 0x10800b5 } public static final class R.raw { @@ -414,13 +414,13 @@ package android { field public static final int config_customMediaKeyDispatcher = 17039404; // 0x104002c field public static final int config_customMediaSessionPolicyProvider = 17039405; // 0x104002d field public static final int config_defaultAssistant = 17039393; // 0x1040021 - field public static final int config_defaultAutomotiveNavigation; + field public static final int config_defaultAutomotiveNavigation = 17039424; // 0x1040040 field public static final int config_defaultBrowser = 17039394; // 0x1040022 field public static final int config_defaultCallRedirection = 17039397; // 0x1040025 field public static final int config_defaultCallScreening = 17039398; // 0x1040026 field public static final int config_defaultDialer = 17039395; // 0x1040023 field public static final int config_defaultSms = 17039396; // 0x1040024 - field public static final int config_devicePolicyManagement; + field public static final int config_devicePolicyManagement = 17039421; // 0x104003d field public static final int config_feedbackIntentExtraKey = 17039391; // 0x104001f field public static final int config_feedbackIntentNameKey = 17039392; // 0x1040020 field public static final int config_helpIntentExtraKey = 17039389; // 0x104001d @@ -429,19 +429,19 @@ package android { field public static final int config_helpPackageNameValue = 17039388; // 0x104001c field public static final int config_systemActivityRecognizer = 17039416; // 0x1040038 field public static final int config_systemAmbientAudioIntelligence = 17039411; // 0x1040033 - field public static final int config_systemAppProtectionService; + field public static final int config_systemAppProtectionService = 17039422; // 0x104003e field public static final int config_systemAudioIntelligence = 17039412; // 0x1040034 - field public static final int config_systemAutomotiveCalendarSyncManager; + field public static final int config_systemAutomotiveCalendarSyncManager = 17039423; // 0x104003f field public static final int config_systemAutomotiveCluster = 17039400; // 0x1040028 field public static final int config_systemAutomotiveProjection = 17039401; // 0x1040029 field public static final int config_systemCompanionDeviceProvider = 17039417; // 0x1040039 field public static final int config_systemContacts = 17039403; // 0x104002b field public static final int config_systemGallery = 17039399; // 0x1040027 field public static final int config_systemNotificationIntelligence = 17039413; // 0x1040035 - field public static final int config_systemSettingsIntelligence; + field public static final int config_systemSettingsIntelligence = 17039426; // 0x1040042 field public static final int config_systemShell = 17039402; // 0x104002a field public static final int config_systemSpeechRecognizer = 17039406; // 0x104002e - field public static final int config_systemSupervision; + field public static final int config_systemSupervision = 17039420; // 0x104003c field public static final int config_systemTelevisionNotificationHandler = 17039409; // 0x1040031 field public static final int config_systemTextIntelligence = 17039414; // 0x1040036 field public static final int config_systemUi = 17039418; // 0x104003a @@ -449,7 +449,7 @@ package android { field public static final int config_systemVisualIntelligence = 17039415; // 0x1040037 field public static final int config_systemWellbeing = 17039408; // 0x1040030 field public static final int config_systemWifiCoexManager = 17039407; // 0x104002f - field public static final int safety_protection_display_text; + field public static final int safety_protection_display_text = 17039425; // 0x1040041 } public static final class R.style { @@ -762,7 +762,7 @@ package android.app { method public void clearRequireCompatChange(); method public boolean isPendingIntentBackgroundActivityLaunchAllowed(); method public static android.app.BroadcastOptions makeBasic(); - method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void recordResponseEventWhileInBackground(@IntRange(from=0) long); + method @RequiresPermission(android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS) public void recordResponseEventWhileInBackground(@IntRange(from=0) long); method @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND) public void setBackgroundActivityStartsAllowed(boolean); method public void setDontSendToRestrictedApps(boolean); method public void setPendingIntentBackgroundActivityLaunchAllowed(boolean); diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 27f5b926411c..f4a12a5a6a0f 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -63,14 +63,14 @@ package android { public static final class R.bool { field public static final int config_assistantOnTopOfDream = 17891333; // 0x1110005 field public static final int config_perDisplayFocusEnabled = 17891332; // 0x1110004 - field public static final int config_preventImeStartupUnlessTextEditor; + field public static final int config_preventImeStartupUnlessTextEditor = 17891335; // 0x1110007 field public static final int config_remoteInsetsControllerControlsSystemBars = 17891334; // 0x1110006 } public static final class R.string { field public static final int config_defaultAssistant = 17039393; // 0x1040021 field public static final int config_defaultDialer = 17039395; // 0x1040023 - field public static final int config_systemAutomotiveCalendarSyncManager; + field public static final int config_systemAutomotiveCalendarSyncManager = 17039423; // 0x104003f field public static final int config_systemAutomotiveCluster = 17039400; // 0x1040028 field public static final int config_systemAutomotiveProjection = 17039401; // 0x1040029 field public static final int config_systemGallery = 17039399; // 0x1040027 diff --git a/core/java/android/accessibilityservice/InputMethod.java b/core/java/android/accessibilityservice/InputMethod.java index c0e5e84d369a..79bac9bce620 100644 --- a/core/java/android/accessibilityservice/InputMethod.java +++ b/core/java/android/accessibilityservice/InputMethod.java @@ -62,7 +62,6 @@ public class InputMethod { private final AccessibilityService mService; private InputBinding mInputBinding; - private InputConnection mInputConnection; private boolean mInputStarted; private InputConnection mStartedInputConnection; private EditorInfo mInputEditorInfo; @@ -81,12 +80,8 @@ public class InputMethod { */ @Nullable public final AccessibilityInputConnection getCurrentInputConnection() { - InputConnection ic = mStartedInputConnection; - if (ic != null) { - return new AccessibilityInputConnection(ic); - } - if (mInputConnection != null) { - return new AccessibilityInputConnection(mInputConnection); + if (mStartedInputConnection != null) { + return new AccessibilityInputConnection(mStartedInputConnection); } return null; } @@ -136,10 +131,8 @@ public class InputMethod { * to perform whatever behavior you would like. */ public void onFinishInput() { - InputConnection ic = mStartedInputConnection != null ? mStartedInputConnection - : mInputConnection; - if (ic != null) { - ic.finishComposingText(); + if (mStartedInputConnection != null) { + mStartedInputConnection.finishComposingText(); } } @@ -176,38 +169,38 @@ public class InputMethod { final void bindInput(@NonNull InputBinding binding) { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AccessibilityService.bindInput"); mInputBinding = binding; - mInputConnection = binding.getConnection(); - Log.v(LOG_TAG, "bindInput(): binding=" + binding - + " ic=" + mInputConnection); + Log.v(LOG_TAG, "bindInput(): binding=" + binding); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } final void unbindInput() { - Log.v(LOG_TAG, "unbindInput(): binding=" + mInputBinding - + " ic=" + mInputConnection); + Log.v(LOG_TAG, "unbindInput(): binding=" + mInputBinding); // Unbind input is per process per display. mInputBinding = null; - mInputConnection = null; } final void startInput(@Nullable InputConnection ic, @NonNull EditorInfo attribute) { Log.v(LOG_TAG, "startInput(): editor=" + attribute); - Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.startInput"); + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AccessibilityService.startInput"); doStartInput(ic, attribute, false /* restarting */); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } final void restartInput(@Nullable InputConnection ic, @NonNull EditorInfo attribute) { Log.v(LOG_TAG, "restartInput(): editor=" + attribute); - Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.restartInput"); + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AccessibilityService.restartInput"); doStartInput(ic, attribute, true /* restarting */); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } final void doStartInput(InputConnection ic, EditorInfo attribute, boolean restarting) { - if (!restarting && mInputStarted) { + if ((ic == null || !restarting) && mInputStarted) { doFinishInput(); + if (ic == null) { + // Unlike InputMethodService, A11y IME should not observe fallback InputConnection. + return; + } } mInputStarted = true; mStartedInputConnection = ic; @@ -224,6 +217,7 @@ public class InputMethod { } mInputStarted = false; mStartedInputConnection = null; + mInputEditorInfo = null; } private InputMethodSession onCreateInputMethodSessionInterface() { @@ -624,7 +618,6 @@ public class InputMethod { @Override public void invalidateInputInternal(EditorInfo editorInfo, IInputContext inputContext, int sessionId) { - // TODO(b/217788708): Add automated test. if (mStartedInputConnection instanceof RemoteInputConnection) { final RemoteInputConnection ric = (RemoteInputConnection) mStartedInputConnection; diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 852dd974ae42..7d68eb92f206 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -4114,8 +4114,8 @@ public final class ActivityThread extends ClientTransactionHandler @NonNull SurfaceControl startingWindowLeash) { final SplashScreenView.Builder builder = new SplashScreenView.Builder(r.activity); final SplashScreenView view = builder.createFromParcel(parcelable).build(); + view.attachHostWindow(r.window); decorView.addView(view); - view.attachHostActivityAndSetSystemUIColors(r.activity, r.window); view.requestLayout(); view.getViewTreeObserver().addOnDrawListener(new ViewTreeObserver.OnDrawListener() { diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java index 8b3c9fa73798..56f8760f6059 100644 --- a/core/java/android/app/BroadcastOptions.java +++ b/core/java/android/app/BroadcastOptions.java @@ -532,7 +532,7 @@ public class BroadcastOptions extends ComponentOptions { * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) + @RequiresPermission(android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS) public void recordResponseEventWhileInBackground(@IntRange(from = 0) long id) { mIdForResponseEvent = id; } diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index 4fbe232556ed..df9f2a3cbb25 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -57,6 +57,7 @@ interface INotificationManager @UnsupportedAppUsage void cancelNotificationWithTag(String pkg, String opPkg, String tag, int id, int userId); + boolean isInCall(String pkg, int uid); void setShowBadge(String pkg, int uid, boolean showBadge); boolean canShowBadge(String pkg, int uid); boolean hasSentValidMsg(String pkg, int uid); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 6e1d1cd2e4c9..56d655c9cc6f 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -628,6 +628,9 @@ public class Notification implements Parcelable * Bit to be bitwise-ored into the {@link #flags} field that should be * set if you would only like the sound, vibrate and ticker to be played * if the notification was not already showing. + * + * Note that using this flag will stop any ongoing alerting behaviour such + * as sound, vibration or blinking notification LED. */ public static final int FLAG_ONLY_ALERT_ONCE = 0x00000008; @@ -2810,8 +2813,8 @@ public class Notification implements Parcelable } if (extras != null) { - visitIconUri(visitor, extras.getParcelable(EXTRA_LARGE_ICON_BIG)); - visitIconUri(visitor, extras.getParcelable(EXTRA_PICTURE_ICON)); + visitIconUri(visitor, extras.getParcelable(EXTRA_LARGE_ICON_BIG, Icon.class)); + visitIconUri(visitor, extras.getParcelable(EXTRA_PICTURE_ICON, Icon.class)); // NOTE: The documentation of EXTRA_AUDIO_CONTENTS_URI explicitly says that it is a // String representation of a Uri, but the previous implementation (and unit test) of @@ -2835,7 +2838,7 @@ public class Notification implements Parcelable } } - final Person person = extras.getParcelable(EXTRA_MESSAGING_PERSON); + final Person person = extras.getParcelable(EXTRA_MESSAGING_PERSON, Person.class); if (person != null) { visitor.accept(person.getIconUri()); } @@ -4633,6 +4636,9 @@ public class Notification implements Parcelable * Set this flag if you would only like the sound, vibrate * and ticker to be played if the notification is not already showing. * + * Note that using this flag will stop any ongoing alerting behaviour such + * as sound, vibration or blinking notification LED. + * * @see Notification#FLAG_ONLY_ALERT_ONCE */ @NonNull @@ -6467,7 +6473,7 @@ public class Notification implements Parcelable public static Notification.Builder recoverBuilder(Context context, Notification n) { // Re-create notification context so we can access app resources. ApplicationInfo applicationInfo = n.extras.getParcelable( - EXTRA_BUILDER_APPLICATION_INFO); + EXTRA_BUILDER_APPLICATION_INFO, ApplicationInfo.class); Context builderContext; if (applicationInfo != null) { try { @@ -6919,9 +6925,8 @@ public class Notification implements Parcelable boolean isMediaStyle = (MediaStyle.class.equals(style) || DecoratedMediaCustomViewStyle.class.equals(style)); - boolean hasMediaSession = (extras.getParcelable(Notification.EXTRA_MEDIA_SESSION) != null - && extras.getParcelable(Notification.EXTRA_MEDIA_SESSION) - instanceof MediaSession.Token); + boolean hasMediaSession = extras.getParcelable(Notification.EXTRA_MEDIA_SESSION, + MediaSession.Token.class) != null; return isMediaStyle && hasMediaSession; } @@ -7516,7 +7521,7 @@ public class Notification implements Parcelable if (extras.containsKey(EXTRA_LARGE_ICON_BIG)) { mBigLargeIconSet = true; - mBigLargeIcon = extras.getParcelable(EXTRA_LARGE_ICON_BIG); + mBigLargeIcon = extras.getParcelable(EXTRA_LARGE_ICON_BIG, Icon.class); } if (extras.containsKey(EXTRA_PICTURE_CONTENT_DESCRIPTION)) { @@ -7536,11 +7541,11 @@ public class Notification implements Parcelable // When this style adds a picture, we only add one of the keys. If both were added, // it would most likely be a legacy app trying to override the picture in some way. // Because of that case it's better to give precedence to the legacy field. - Bitmap bitmapPicture = extras.getParcelable(EXTRA_PICTURE); + Bitmap bitmapPicture = extras.getParcelable(EXTRA_PICTURE, Bitmap.class); if (bitmapPicture != null) { return Icon.createWithBitmap(bitmapPicture); } else { - return extras.getParcelable(EXTRA_PICTURE_ICON); + return extras.getParcelable(EXTRA_PICTURE_ICON, Icon.class); } } @@ -7917,6 +7922,8 @@ public class Notification implements Parcelable * @hide */ public MessagingStyle setShortcutIcon(@Nullable Icon conversationIcon) { + // TODO(b/228941516): This icon should be downscaled to avoid using too much memory, + // see reduceImageSizes. mShortcutIcon = conversationIcon; return this; } @@ -8157,7 +8164,7 @@ public class Notification implements Parcelable protected void restoreFromExtras(Bundle extras) { super.restoreFromExtras(extras); - mUser = extras.getParcelable(EXTRA_MESSAGING_PERSON); + mUser = extras.getParcelable(EXTRA_MESSAGING_PERSON, Person.class); if (mUser == null) { CharSequence displayName = extras.getCharSequence(EXTRA_SELF_DISPLAY_NAME); mUser = new Person.Builder().setName(displayName).build(); @@ -8169,7 +8176,7 @@ public class Notification implements Parcelable mHistoricMessages = Message.getMessagesFromBundleArray(histMessages); mIsGroupConversation = extras.getBoolean(EXTRA_IS_GROUP_CONVERSATION); mUnreadMessageCount = extras.getInt(EXTRA_CONVERSATION_UNREAD_MESSAGE_COUNT); - mShortcutIcon = extras.getParcelable(EXTRA_CONVERSATION_ICON); + mShortcutIcon = extras.getParcelable(EXTRA_CONVERSATION_ICON, Icon.class); } /** @@ -8423,6 +8430,51 @@ public class Notification implements Parcelable return makeMessagingView(StandardTemplateParams.VIEW_TYPE_HEADS_UP); } + /** + * @hide + */ + @Override + public void reduceImageSizes(Context context) { + super.reduceImageSizes(context); + Resources resources = context.getResources(); + boolean isLowRam = ActivityManager.isLowRamDeviceStatic(); + if (mShortcutIcon != null) { + int maxSize = resources.getDimensionPixelSize( + isLowRam ? R.dimen.notification_small_icon_size_low_ram + : R.dimen.notification_small_icon_size); + mShortcutIcon.scaleDownIfNecessary(maxSize, maxSize); + } + + int maxAvatarSize = resources.getDimensionPixelSize( + isLowRam ? R.dimen.notification_person_icon_max_size + : R.dimen.notification_person_icon_max_size_low_ram); + if (mUser != null && mUser.getIcon() != null) { + mUser.getIcon().scaleDownIfNecessary(maxAvatarSize, maxAvatarSize); + } + + reduceMessagesIconSizes(mMessages, maxAvatarSize); + reduceMessagesIconSizes(mHistoricMessages, maxAvatarSize); + } + + /** + * @hide + */ + private static void reduceMessagesIconSizes(@Nullable List<Message> messages, int maxSize) { + if (messages == null) { + return; + } + + for (Message message : messages) { + Person sender = message.mSender; + if (sender != null) { + Icon icon = sender.getIcon(); + if (icon != null) { + icon.scaleDownIfNecessary(maxSize, maxSize); + } + } + } + } + public static final class Message { /** @hide */ public static final String KEY_TEXT = "text"; @@ -8678,7 +8730,7 @@ public class Notification implements Parcelable return null; } else { - Person senderPerson = bundle.getParcelable(KEY_SENDER_PERSON); + Person senderPerson = bundle.getParcelable(KEY_SENDER_PERSON, Person.class); if (senderPerson == null) { // Legacy apps that use compat don't actually provide the sender objects // We need to fix the compat version to provide people / use @@ -8695,7 +8747,7 @@ public class Notification implements Parcelable if (bundle.containsKey(KEY_DATA_MIME_TYPE) && bundle.containsKey(KEY_DATA_URI)) { message.setData(bundle.getString(KEY_DATA_MIME_TYPE), - (Uri) bundle.getParcelable(KEY_DATA_URI)); + bundle.getParcelable(KEY_DATA_URI, Uri.class)); } if (bundle.containsKey(KEY_EXTRAS_BUNDLE)) { message.getExtras().putAll(bundle.getBundle(KEY_EXTRAS_BUNDLE)); @@ -9101,7 +9153,7 @@ public class Notification implements Parcelable super.restoreFromExtras(extras); if (extras.containsKey(EXTRA_MEDIA_SESSION)) { - mToken = extras.getParcelable(EXTRA_MEDIA_SESSION); + mToken = extras.getParcelable(EXTRA_MEDIA_SESSION, MediaSession.Token.class); } if (extras.containsKey(EXTRA_COMPACT_ACTIONS)) { mActionsToShowInCompact = extras.getIntArray(EXTRA_COMPACT_ACTIONS); @@ -9113,7 +9165,8 @@ public class Notification implements Parcelable mDeviceIcon = extras.getInt(EXTRA_MEDIA_REMOTE_ICON); } if (extras.containsKey(EXTRA_MEDIA_REMOTE_INTENT)) { - mDeviceIntent = extras.getParcelable(EXTRA_MEDIA_REMOTE_INTENT); + mDeviceIntent = extras.getParcelable( + EXTRA_MEDIA_REMOTE_INTENT, PendingIntent.class); } } @@ -9705,12 +9758,12 @@ public class Notification implements Parcelable super.restoreFromExtras(extras); mCallType = extras.getInt(EXTRA_CALL_TYPE); mIsVideo = extras.getBoolean(EXTRA_CALL_IS_VIDEO); - mPerson = extras.getParcelable(EXTRA_CALL_PERSON); + mPerson = extras.getParcelable(EXTRA_CALL_PERSON, Person.class); mVerificationIcon = extras.getParcelable(EXTRA_VERIFICATION_ICON); mVerificationText = extras.getCharSequence(EXTRA_VERIFICATION_TEXT); - mAnswerIntent = extras.getParcelable(EXTRA_ANSWER_INTENT); - mDeclineIntent = extras.getParcelable(EXTRA_DECLINE_INTENT); - mHangUpIntent = extras.getParcelable(EXTRA_HANG_UP_INTENT); + mAnswerIntent = extras.getParcelable(EXTRA_ANSWER_INTENT, PendingIntent.class); + mDeclineIntent = extras.getParcelable(EXTRA_DECLINE_INTENT, PendingIntent.class); + mHangUpIntent = extras.getParcelable(EXTRA_HANG_UP_INTENT, PendingIntent.class); mAnswerButtonColor = extras.containsKey(EXTRA_ANSWER_COLOR) ? extras.getInt(EXTRA_ANSWER_COLOR) : null; mDeclineButtonColor = extras.containsKey(EXTRA_DECLINE_COLOR) @@ -10771,9 +10824,9 @@ public class Notification implements Parcelable // Keys within EXTRA_WEARABLE_EXTENSIONS for wearable options. private static final String KEY_ACTIONS = "actions"; private static final String KEY_FLAGS = "flags"; - private static final String KEY_DISPLAY_INTENT = "displayIntent"; + static final String KEY_DISPLAY_INTENT = "displayIntent"; private static final String KEY_PAGES = "pages"; - private static final String KEY_BACKGROUND = "background"; + static final String KEY_BACKGROUND = "background"; private static final String KEY_CONTENT_ICON = "contentIcon"; private static final String KEY_CONTENT_ICON_GRAVITY = "contentIconGravity"; private static final String KEY_CONTENT_ACTION_INDEX = "contentActionIndex"; @@ -10830,7 +10883,8 @@ public class Notification implements Parcelable } mFlags = wearableBundle.getInt(KEY_FLAGS, DEFAULT_FLAGS); - mDisplayIntent = wearableBundle.getParcelable(KEY_DISPLAY_INTENT); + mDisplayIntent = wearableBundle.getParcelable( + KEY_DISPLAY_INTENT, PendingIntent.class); Notification[] pages = getParcelableArrayFromBundle( wearableBundle, KEY_PAGES, Notification.class); @@ -10838,7 +10892,7 @@ public class Notification implements Parcelable Collections.addAll(mPages, pages); } - mBackground = wearableBundle.getParcelable(KEY_BACKGROUND); + mBackground = wearableBundle.getParcelable(KEY_BACKGROUND, Bitmap.class); mContentIcon = wearableBundle.getInt(KEY_CONTENT_ICON); mContentIconGravity = wearableBundle.getInt(KEY_CONTENT_ICON_GRAVITY, DEFAULT_CONTENT_ICON_GRAVITY); @@ -11551,7 +11605,7 @@ public class Notification implements Parcelable Bundle carBundle = notif.extras == null ? null : notif.extras.getBundle(EXTRA_CAR_EXTENDER); if (carBundle != null) { - mLargeIcon = carBundle.getParcelable(EXTRA_LARGE_ICON); + mLargeIcon = carBundle.getParcelable(EXTRA_LARGE_ICON, Bitmap.class); mColor = carBundle.getInt(EXTRA_COLOR, Notification.COLOR_DEFAULT); Bundle b = carBundle.getBundle(EXTRA_CONVERSATION); @@ -11657,9 +11711,9 @@ public class Notification implements Parcelable private static final String KEY_AUTHOR = "author"; private static final String KEY_TEXT = "text"; private static final String KEY_MESSAGES = "messages"; - private static final String KEY_REMOTE_INPUT = "remote_input"; - private static final String KEY_ON_REPLY = "on_reply"; - private static final String KEY_ON_READ = "on_read"; + static final String KEY_REMOTE_INPUT = "remote_input"; + static final String KEY_ON_REPLY = "on_reply"; + static final String KEY_ON_READ = "on_read"; private static final String KEY_PARTICIPANTS = "participants"; private static final String KEY_TIMESTAMP = "timestamp"; @@ -11784,10 +11838,10 @@ public class Notification implements Parcelable } } - PendingIntent onRead = b.getParcelable(KEY_ON_READ); - PendingIntent onReply = b.getParcelable(KEY_ON_REPLY); + PendingIntent onRead = b.getParcelable(KEY_ON_READ, PendingIntent.class); + PendingIntent onReply = b.getParcelable(KEY_ON_REPLY, PendingIntent.class); - RemoteInput remoteInput = b.getParcelable(KEY_REMOTE_INPUT); + RemoteInput remoteInput = b.getParcelable(KEY_REMOTE_INPUT, RemoteInput.class); String[] participants = b.getStringArray(KEY_PARTICIPANTS); if (participants == null || participants.length != 1) { @@ -11929,8 +11983,8 @@ public class Notification implements Parcelable private static final String EXTRA_TV_EXTENDER = "android.tv.EXTENSIONS"; private static final String EXTRA_FLAGS = "flags"; - private static final String EXTRA_CONTENT_INTENT = "content_intent"; - private static final String EXTRA_DELETE_INTENT = "delete_intent"; + static final String EXTRA_CONTENT_INTENT = "content_intent"; + static final String EXTRA_DELETE_INTENT = "delete_intent"; private static final String EXTRA_CHANNEL_ID = "channel_id"; private static final String EXTRA_SUPPRESS_SHOW_OVER_APPS = "suppressShowOverApps"; @@ -11962,8 +12016,8 @@ public class Notification implements Parcelable mFlags = bundle.getInt(EXTRA_FLAGS); mChannelId = bundle.getString(EXTRA_CHANNEL_ID); mSuppressShowOverApps = bundle.getBoolean(EXTRA_SUPPRESS_SHOW_OVER_APPS); - mContentIntent = bundle.getParcelable(EXTRA_CONTENT_INTENT); - mDeleteIntent = bundle.getParcelable(EXTRA_DELETE_INTENT); + mContentIntent = bundle.getParcelable(EXTRA_CONTENT_INTENT, PendingIntent.class); + mDeleteIntent = bundle.getParcelable(EXTRA_DELETE_INTENT, PendingIntent.class); } } diff --git a/core/java/android/app/PropertyInvalidatedCache.java b/core/java/android/app/PropertyInvalidatedCache.java index df7bf7b94700..add891d40d95 100644 --- a/core/java/android/app/PropertyInvalidatedCache.java +++ b/core/java/android/app/PropertyInvalidatedCache.java @@ -313,6 +313,7 @@ public class PropertyInvalidatedCache<Query, Result> { * one of the permitted values above. The API is a string that is a legal Java simple * identifier. The api is modified to conform to the system property style guide by * replacing every upper case letter with an underscore and the lower case equivalent. + * (An initial upper case letter is not prefixed with an underscore). * There is no requirement that the apiName be the name of an actual API. * * Be aware that SystemProperties has a maximum length which is private to the @@ -326,7 +327,7 @@ public class PropertyInvalidatedCache<Query, Result> { @NonNull String apiName) { char[] api = apiName.toCharArray(); int upper = 0; - for (int i = 0; i < api.length; i++) { + for (int i = 1; i < api.length; i++) { if (Character.isUpperCase(api[i])) { upper++; } @@ -336,7 +337,9 @@ public class PropertyInvalidatedCache<Query, Result> { for (int i = 0; i < api.length; i++) { if (Character.isJavaIdentifierPart(api[i])) { if (Character.isUpperCase(api[i])) { - suffix[j++] = '_'; + if (i > 0) { + suffix[j++] = '_'; + } suffix[j++] = Character.toLowerCase(api[i]); } else { suffix[j++] = api[i]; @@ -1286,13 +1289,23 @@ public class PropertyInvalidatedCache<Query, Result> { } /** - * Return the name of the cache, to be used in debug messages. + * Return the name of the cache, to be used in debug messages. This is exposed + * primarily for testing. + * @hide */ - private final @NonNull String cacheName() { + public final @NonNull String cacheName() { return mCacheName; } /** + * Return the property used by the cache. This is primarily for test purposes. + * @hide + */ + public final @NonNull String propertyName() { + return mPropertyName; + } + + /** * Return the query as a string, to be used in debug messages. New clients should not * override this, but should instead add the necessary toString() method to the Query * class. diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 0a18588e0131..e022ca306674 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -67,7 +67,6 @@ import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.StrictMode; import android.os.SystemProperties; -import android.service.wallpaper.WallpaperService; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -559,23 +558,26 @@ public class WallpaperManager { } mCachedWallpaper = null; mCachedWallpaperUserId = 0; - try { - mCachedWallpaper = getCurrentWallpaperLocked( - context, userId, hardware, cmProxy); - mCachedWallpaperUserId = userId; - } catch (OutOfMemoryError e) { - Log.w(TAG, "Out of memory loading the current wallpaper: " + e); - } catch (SecurityException e) { - if (context.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.O_MR1) { - Log.w(TAG, "No permission to access wallpaper, suppressing" - + " exception to avoid crashing legacy app."); - } else { - // Post-O apps really most sincerely need the permission. - throw e; + } + try { + Bitmap currentWallpaper = getCurrentWallpaperLocked( + context, userId, hardware, cmProxy); + if (currentWallpaper != null) { + synchronized (this) { + mCachedWallpaper = currentWallpaper; + mCachedWallpaperUserId = userId; + return mCachedWallpaper; } } - if (mCachedWallpaper != null) { - return mCachedWallpaper; + } catch (OutOfMemoryError e) { + Log.w(TAG, "Out of memory loading the current wallpaper: " + e); + } catch (SecurityException e) { + if (context.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.O_MR1) { + Log.w(TAG, "No permission to access wallpaper, suppressing" + + " exception to avoid crashing legacy app."); + } else { + // Post-O apps really most sincerely need the permission. + throw e; } } if (returnDefault) { @@ -2472,7 +2474,7 @@ public class WallpaperManager { * * @param colors Wallpaper color info, {@code null} when not available. * @param which A combination of {@link #FLAG_LOCK} and {@link #FLAG_SYSTEM} - * @see WallpaperService.Engine#onComputeColors() + * @see android.service.wallpaper.WallpaperService.Engine#onComputeColors() */ void onColorsChanged(@Nullable WallpaperColors colors, int which); @@ -2484,7 +2486,7 @@ public class WallpaperManager { * @param colors Wallpaper color info, {@code null} when not available. * @param which A combination of {@link #FLAG_LOCK} and {@link #FLAG_SYSTEM} * @param userId Owner of the wallpaper - * @see WallpaperService.Engine#onComputeColors() + * @see android.service.wallpaper.WallpaperService.Engine#onComputeColors() * @hide */ default void onColorsChanged(@Nullable WallpaperColors colors, int which, int userId) { diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index d375a9e1ba26..d11b23cc871b 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -185,6 +185,30 @@ public class DevicePolicyManager { mResourcesManager = new DevicePolicyResourcesManager(context, service); } + /** + * Fetch the current value of mService. This is used in the binder cache lambda + * expressions. + */ + private final IDevicePolicyManager getService() { + return mService; + } + + /** + * Fetch the current value of mParentInstance. This is used in the binder cache + * lambda expressions. + */ + private final boolean isParentInstance() { + return mParentInstance; + } + + /** + * Fetch the current value of mContext. This is used in the binder cache lambda + * expressions. + */ + private final Context getContext() { + return mContext; + } + /** @hide test will override it. */ @VisibleForTesting protected int myUserId() { @@ -2518,7 +2542,7 @@ public class DevicePolicyManager { * that has this delegation. If another app already had delegated security logging access, it * will lose the delegation when a new app is delegated. * - * <p> Can only be granted by Device Owner or Profile Owner of an organnization owned and + * <p> Can only be granted by Device Owner or Profile Owner of an organization-owned * managed profile. */ public static final String DELEGATION_SECURITY_LOGGING = "delegation-security-logging"; @@ -3783,57 +3807,21 @@ public class DevicePolicyManager { "android.app.extra.RESOURCE_IDS"; /** - * A convenience class that wraps some IpcDataCache methods. Instantiate it with an - * API string. Instances can and should be final static. All instances of this class - * use the same key for invalidation. + * This object is a single place to tack on invalidation and disable calls. All + * binder caches in this class derive from this Config, so all can be invalidated or + * disabled through this Config. */ - private static class BinderApi { - private final static String KEY = "DevicePolicyManager"; - private final String mApi; - BinderApi(String api) { - mApi = api; - } - final String api() { - return mApi; - } - final String key() { - return KEY; - } - final static void invalidate() { - IpcDataCache.invalidateCache(IpcDataCache.MODULE_SYSTEM, KEY); - } - final void disable() { - IpcDataCache.disableForCurrentProcess(mApi); - } - } + private static final IpcDataCache.Config sDpmCaches = + new IpcDataCache.Config(8, IpcDataCache.MODULE_SYSTEM, "DevicePolicyManagerCaches"); /** @hide */ public static void invalidateBinderCaches() { - BinderApi.invalidate(); - } - - /** - * A simple wrapper for binder caches in this class. All caches are created with a - * maximum of 8 entries, the SYSTEM module, and a cache name that is the same as the api. - */ - private static class BinderCache<Q,R> extends IpcDataCache<Q,R> { - BinderCache(BinderApi api, IpcDataCache.QueryHandler<Q,R> handler) { - super(8, IpcDataCache.MODULE_SYSTEM, api.key(), api.api(), handler); - } + sDpmCaches.invalidateCache(); } - /** - * Disable all caches in the local process. - * @hide - */ - public static void disableLocalProcessCaches() { - disableGetKeyguardDisabledFeaturesCache(); - disableHasDeviceOwnerCache(); - disableGetProfileOwnerOrDeviceOwnerSupervisionComponentCache(); - disableIsOrganizationOwnedDeviceWithManagedProfileCache(); - disableGetDeviceOwnerOrganizationNameCache(); - disableGetOrganizationNameForUserCache(); - disableIsNetworkLoggingEnabled(); + /** @hide */ + public static void disableLocalCaches() { + sDpmCaches.disableAllForCurrentProcess(); } /** @hide */ @@ -8435,54 +8423,16 @@ public class DevicePolicyManager { return getKeyguardDisabledFeatures(admin, myUserId()); } - // A key into the keyguard cache. - private static class KeyguardQuery { - private final ComponentName mAdmin; - private final int mUserHandle; - KeyguardQuery(@Nullable ComponentName admin, int userHandle) { - mAdmin = admin; - mUserHandle = userHandle; - } - public boolean equals(Object o) { - if (o instanceof KeyguardQuery) { - KeyguardQuery r = (KeyguardQuery) o; - return Objects.equals(mAdmin, r.mAdmin) && mUserHandle == r.mUserHandle; - } else { - return false; - } - } - public int hashCode() { - return ((mAdmin != null) ? mAdmin.hashCode() : 0) * 13 + mUserHandle; - } - } - - // The query handler does not cache wildcard user IDs, although they should never - // appear in the query. - private static final BinderApi sGetKeyguardDisabledFeatures = - new BinderApi("getKeyguardDisabledFeatures"); - private BinderCache<KeyguardQuery, Integer> mGetKeyGuardDisabledFeaturesCache = - new BinderCache<>(sGetKeyguardDisabledFeatures, - new IpcDataCache.QueryHandler<KeyguardQuery, Integer>() { - @Override - public Integer apply(KeyguardQuery query) { - try { - return mService.getKeyguardDisabledFeatures( - query.mAdmin, query.mUserHandle, mParentInstance); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - }}); - - /** @hide */ - public static void disableGetKeyguardDisabledFeaturesCache() { - sGetKeyguardDisabledFeatures.disable(); - } + private IpcDataCache<Pair<ComponentName, Integer>, Integer> mGetKeyGuardDisabledFeaturesCache = + new IpcDataCache<>(sDpmCaches.child("getKeyguardDisabledFeatures"), + (query) -> getService().getKeyguardDisabledFeatures( + query.first, query.second, isParentInstance())); /** @hide per-user version */ @UnsupportedAppUsage public int getKeyguardDisabledFeatures(@Nullable ComponentName admin, int userHandle) { if (mService != null) { - return mGetKeyGuardDisabledFeaturesCache.query(new KeyguardQuery(admin, userHandle)); + return mGetKeyGuardDisabledFeaturesCache.query(new Pair<>(admin, userHandle)); } else { return KEYGUARD_DISABLE_FEATURES_NONE; } @@ -8864,23 +8814,9 @@ public class DevicePolicyManager { return name != null ? name.getPackageName() : null; } - private static final BinderApi sHasDeviceOwner = - new BinderApi("hasDeviceOwner"); - private BinderCache<Void, Boolean> mHasDeviceOwnerCache = - new BinderCache<>(sHasDeviceOwner, - new IpcDataCache.QueryHandler<Void, Boolean>() { - @Override - public Boolean apply(Void query) { - try { - return mService.hasDeviceOwner(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - }}); - /** @hide */ - public static void disableHasDeviceOwnerCache() { - sHasDeviceOwner.disable(); - } + private IpcDataCache<Void, Boolean> mHasDeviceOwnerCache = + new IpcDataCache<>(sDpmCaches.child("hasDeviceOwner"), + (query) -> getService().hasDeviceOwner()); /** * Called by the system to find out whether the device is managed by a Device Owner. @@ -9256,25 +9192,10 @@ public class DevicePolicyManager { return null; } - private final static BinderApi sGetProfileOwnerOrDeviceOwnerSupervisionComponent = - new BinderApi("getProfileOwnerOrDeviceOwnerSupervisionComponent"); - private final BinderCache<UserHandle, ComponentName> + private final IpcDataCache<UserHandle, ComponentName> mGetProfileOwnerOrDeviceOwnerSupervisionComponentCache = - new BinderCache(sGetProfileOwnerOrDeviceOwnerSupervisionComponent, - new IpcDataCache.QueryHandler<UserHandle, ComponentName>() { - @Override - public ComponentName apply(UserHandle user) { - try { - return mService.getProfileOwnerOrDeviceOwnerSupervisionComponent( - user); - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); - } - }}); - /** @hide */ - public static void disableGetProfileOwnerOrDeviceOwnerSupervisionComponentCache() { - sGetProfileOwnerOrDeviceOwnerSupervisionComponent.disable(); - } + new IpcDataCache<>(sDpmCaches.child("getProfileOwnerOrDeviceOwnerSupervisionComponent"), + (arg) -> getService().getProfileOwnerOrDeviceOwnerSupervisionComponent(arg)); /** * Returns the configured supervision app if it exists and is the device owner or policy owner. @@ -9329,23 +9250,9 @@ public class DevicePolicyManager { return null; } - private final static BinderApi sIsOrganizationOwnedDeviceWithManagedProfile = - new BinderApi("isOrganizationOwnedDeviceWithManagedProfile"); - private final BinderCache<Void, Boolean> mIsOrganizationOwnedDeviceWithManagedProfileCache = - new BinderCache(sIsOrganizationOwnedDeviceWithManagedProfile, - new IpcDataCache.QueryHandler<Void, Boolean>() { - @Override - public Boolean apply(Void query) { - try { - return mService.isOrganizationOwnedDeviceWithManagedProfile(); - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); - } - }}); - /** @hide */ - public static void disableIsOrganizationOwnedDeviceWithManagedProfileCache() { - sIsOrganizationOwnedDeviceWithManagedProfile.disable(); - } + private final IpcDataCache<Void, Boolean> mIsOrganizationOwnedDeviceWithManagedProfileCache = + new IpcDataCache(sDpmCaches.child("isOrganizationOwnedDeviceWithManagedProfile"), + (query) -> getService().isOrganizationOwnedDeviceWithManagedProfile()); /** * Apps can use this method to find out if the device was provisioned as @@ -12927,23 +12834,9 @@ public class DevicePolicyManager { } } - private final static BinderApi sGetDeviceOwnerOrganizationName = - new BinderApi("getDeviceOwnerOrganizationName"); - private final BinderCache<Void, CharSequence> mGetDeviceOwnerOrganizationNameCache = - new BinderCache(sGetDeviceOwnerOrganizationName, - new IpcDataCache.QueryHandler<Void, CharSequence>() { - @Override - public CharSequence apply(Void query) { - try { - return mService.getDeviceOwnerOrganizationName(); - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); - } - }}); - /** @hide */ - public static void disableGetDeviceOwnerOrganizationNameCache() { - sGetDeviceOwnerOrganizationName.disable(); - } + private final IpcDataCache<Void, CharSequence> mGetDeviceOwnerOrganizationNameCache = + new IpcDataCache(sDpmCaches.child("getDeviceOwnerOrganizationName"), + (query) -> getService().getDeviceOwnerOrganizationName()); /** * Called by the system to retrieve the name of the organization managing the device. @@ -12960,23 +12853,9 @@ public class DevicePolicyManager { return mGetDeviceOwnerOrganizationNameCache.query(null); } - private final static BinderApi sGetOrganizationNameForUser = - new BinderApi("getOrganizationNameForUser"); - private final BinderCache<Integer, CharSequence> mGetOrganizationNameForUserCache = - new BinderCache(sGetOrganizationNameForUser, - new IpcDataCache.QueryHandler<Integer, CharSequence>() { - @Override - public CharSequence apply(Integer userHandle) { - try { - return mService.getOrganizationNameForUser(userHandle); - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); - } - }}); - /** @hide */ - public static void disableGetOrganizationNameForUserCache() { - sGetOrganizationNameForUser.disable(); - } + private final IpcDataCache<Integer, CharSequence> mGetOrganizationNameForUserCache = + new IpcDataCache<>(sDpmCaches.child("getOrganizationNameForUser"), + (query) -> getService().getOrganizationNameForUser(query)); /** * Retrieve the default title message used in the confirm credentials screen for a given user. @@ -13372,24 +13251,10 @@ public class DevicePolicyManager { } } - private final static BinderApi sNetworkLoggingApi = new BinderApi("isNetworkLoggingEnabled"); - private BinderCache<ComponentName, Boolean> mIsNetworkLoggingEnabledCache = - new BinderCache<>(sNetworkLoggingApi, - new IpcDataCache.QueryHandler<ComponentName, Boolean>() { - @Override - public Boolean apply(ComponentName admin) { - try { - return mService.isNetworkLoggingEnabled( - admin, mContext.getPackageName()); - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); - } - }}); - - /** @hide */ - public static void disableIsNetworkLoggingEnabled() { - sNetworkLoggingApi.disable(); - } + private IpcDataCache<ComponentName, Boolean> mIsNetworkLoggingEnabledCache = + new IpcDataCache<>(sDpmCaches.child("isNetworkLoggingEnabled"), + (admin) -> getService().isNetworkLoggingEnabled(admin, + getContext().getPackageName())); /** * Return whether network logging is enabled by a device owner or profile owner of diff --git a/core/java/android/app/admin/DevicePolicyResourcesManager.java b/core/java/android/app/admin/DevicePolicyResourcesManager.java index 06729222dea1..e8eb792f7fd7 100644 --- a/core/java/android/app/admin/DevicePolicyResourcesManager.java +++ b/core/java/android/app/admin/DevicePolicyResourcesManager.java @@ -70,6 +70,7 @@ public class DevicePolicyResourcesManager { * * <p>Important notes to consider when using this API: * <ul> + * <li> Updated resources are persisted over reboots. * <li>{@link #getDrawable} references the resource * {@link DevicePolicyDrawableResource#getResourceIdInCallingPackage()} in the * calling package each time it gets called. You have to ensure that the resource is always @@ -381,7 +382,9 @@ public class DevicePolicyResourcesManager { * * <p>Important notes to consider when using this API: * <ul> - * <li> {@link #getString} references the resource {@code callingPackageResourceId} in the + * <li> Updated resources are persisted over reboots. + * <li> {@link #getString} references the resource + * {@link DevicePolicyStringResource#getResourceIdInCallingPackage()} in the * calling package each time it gets called. You have to ensure that the resource is always * available in the calling package as long as it is used as an updated resource. * <li> You still have to re-call {@code setStrings} even if you only make changes to the diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING index dea083422612..cc62d5337c02 100644 --- a/core/java/android/content/pm/TEST_MAPPING +++ b/core/java/android/content/pm/TEST_MAPPING @@ -180,7 +180,7 @@ "name": "CtsAppSecurityHostTestCases", "options": [ { - "include-filter": "com.android.cts.splitapp.SplitAppTest" + "include-filter": "android.appsecurity.cts.SplitTests" }, { "include-filter": "android.appsecurity.cts.EphemeralTest" @@ -199,14 +199,6 @@ "name": "CtsRollbackManagerHostTestCases" }, { - "name": "CtsOsHostTestCases", - "options": [ - { - "include-filter": "com.android.server.pm.PackageParserTest" - } - ] - }, - { "name": "CtsContentTestCases", "options": [ { diff --git a/core/java/android/hardware/CameraSessionStats.java b/core/java/android/hardware/CameraSessionStats.java index 698cc76f6325..9ef63065c057 100644 --- a/core/java/android/hardware/CameraSessionStats.java +++ b/core/java/android/hardware/CameraSessionStats.java @@ -61,6 +61,7 @@ public class CameraSessionStats implements Parcelable { private boolean mDeviceError; private float mMaxPreviewFps; private ArrayList<CameraStreamStats> mStreamStats; + private String mUserTag; public CameraSessionStats() { mFacing = -1; @@ -131,6 +132,7 @@ public class CameraSessionStats implements Parcelable { dest.writeLong(mResultErrorCount); dest.writeBoolean(mDeviceError); dest.writeTypedList(mStreamStats); + dest.writeString(mUserTag); } public void readFromParcel(Parcel in) { @@ -151,6 +153,8 @@ public class CameraSessionStats implements Parcelable { ArrayList<CameraStreamStats> streamStats = new ArrayList<CameraStreamStats>(); in.readTypedList(streamStats, CameraStreamStats.CREATOR); mStreamStats = streamStats; + + mUserTag = in.readString(); } public String getCameraId() { @@ -208,4 +212,8 @@ public class CameraSessionStats implements Parcelable { public List<CameraStreamStats> getStreamStats() { return mStreamStats; } + + public String getUserTag() { + return mUserTag; + } } diff --git a/core/java/android/hardware/fingerprint/FingerprintStateListener.java b/core/java/android/hardware/biometrics/BiometricStateListener.java index 551f5120ce2a..2ac0c1edaef0 100644 --- a/core/java/android/hardware/fingerprint/FingerprintStateListener.java +++ b/core/java/android/hardware/biometrics/BiometricStateListener.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.hardware.fingerprint; +package android.hardware.biometrics; import android.annotation.IntDef; @@ -22,10 +22,10 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** - * Interface for handling state changes in fingerprint-related events. + * Interface for handling state changes in biometric sensors. * @hide */ -public abstract class FingerprintStateListener extends IFingerprintStateListener.Stub { +public abstract class BiometricStateListener extends IBiometricStateListener.Stub { // Operation has not started yet. public static final int STATE_IDLE = 0; @@ -43,16 +43,19 @@ public abstract class FingerprintStateListener extends IFingerprintStateListener @IntDef({STATE_IDLE, STATE_ENROLLING, STATE_KEYGUARD_AUTH, STATE_BP_AUTH, STATE_AUTH_OTHER}) @Retention(RetentionPolicy.SOURCE) - public @interface State {} + public @interface State { + } /** * Defines behavior in response to state update - * @param newState new state of fingerprint sensor + * @param newState new state of the biometric sensor */ - public void onStateChanged(@FingerprintStateListener.State int newState) {} + public void onStateChanged(@BiometricStateListener.State int newState) { + } /** * Invoked when enrollment state changes for the specified user */ - public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {} + public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) { + } } diff --git a/core/java/android/hardware/fingerprint/IFingerprintStateListener.aidl b/core/java/android/hardware/biometrics/IBiometricStateListener.aidl index 1aa6fa197066..5bdced034017 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintStateListener.aidl +++ b/core/java/android/hardware/biometrics/IBiometricStateListener.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 The Android Open Source Project + * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,16 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package android.hardware.fingerprint; - -import android.hardware.fingerprint.Fingerprint; +package android.hardware.biometrics; /** - * Communication channel for FingerprintManager to register the FingerprintStateListener - * in FingerprintService. + * Communication channel between <Biometric>Manager and <Biometric>Service for passing the + * listener. * @hide */ -oneway interface IFingerprintStateListener { +oneway interface IBiometricStateListener { void onStateChanged(int newState); void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments); } diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index d94ad3aa1732..15e59e03ee70 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -266,6 +266,8 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> private int mRequestType = -1; + private static final String SET_TAG_STRING_PREFIX = + "android.hardware.camera2.CaptureRequest.setTag."; /** * Get the type of the capture request * @@ -614,6 +616,11 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> throw new RuntimeException("Reading cached CaptureRequest is not supported"); } } + + boolean hasUserTagStr = (in.readInt() == 1) ? true : false; + if (hasUserTagStr) { + mUserTag = in.readString(); + } } @Override @@ -656,6 +663,19 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> dest.writeInt(0); } } + + // Write string for user tag if set to something in the same namespace + if (mUserTag != null) { + String userTagStr = mUserTag.toString(); + if (userTagStr != null && userTagStr.startsWith(SET_TAG_STRING_PREFIX)) { + dest.writeInt(1); + dest.writeString(userTagStr.substring(SET_TAG_STRING_PREFIX.length())); + } else { + dest.writeInt(0); + } + } else { + dest.writeInt(0); + } } /** @@ -938,7 +958,10 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <p>This tag is not used for anything by the camera device, but can be * used by an application to easily identify a CaptureRequest when it is * returned by - * {@link CameraCaptureSession.CaptureCallback#onCaptureCompleted CaptureCallback.onCaptureCompleted} + * {@link CameraCaptureSession.CaptureCallback#onCaptureCompleted CaptureCallback.onCaptureCompleted}.</p> + * + * <p>If the application overrides the tag object's {@link Object#toString} function, the + * returned string must not contain personal identifiable information.</p> * * @param tag an arbitrary Object to store with this request * @see CaptureRequest#getTag @@ -1387,6 +1410,14 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * region and output only the intersection rectangle as the metering region in the result * metadata. If the region is entirely outside the crop region, it will be ignored and * not reported in the result metadata.</p> + * <p>When setting the AE metering regions, the application must consider the additional + * crop resulted from the aspect ratio differences between the preview stream and + * {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}. For example, if the {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} is the full + * active array size with 4:3 aspect ratio, and the preview stream is 16:9, + * the boundary of AE regions will be [0, y_crop] and + * [active_width, active_height - 2 * y_crop] rather than [0, 0] and + * [active_width, active_height], where y_crop is the additional crop due to aspect ratio + * mismatch.</p> * <p>Starting from API level 30, the coordinate system of activeArraySize or * preCorrectionActiveArraySize is used to represent post-zoomRatio field of view, not * pre-zoom field of view. This means that the same aeRegions values at different @@ -1609,6 +1640,14 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * region and output only the intersection rectangle as the metering region in the result * metadata. If the region is entirely outside the crop region, it will be ignored and * not reported in the result metadata.</p> + * <p>When setting the AF metering regions, the application must consider the additional + * crop resulted from the aspect ratio differences between the preview stream and + * {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}. For example, if the {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} is the full + * active array size with 4:3 aspect ratio, and the preview stream is 16:9, + * the boundary of AF regions will be [0, y_crop] and + * [active_width, active_height - 2 * y_crop] rather than [0, 0] and + * [active_width, active_height], where y_crop is the additional crop due to aspect ratio + * mismatch.</p> * <p>Starting from API level 30, the coordinate system of activeArraySize or * preCorrectionActiveArraySize is used to represent post-zoomRatio field of view, not * pre-zoom field of view. This means that the same afRegions values at different @@ -1823,6 +1862,14 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * region and output only the intersection rectangle as the metering region in the result * metadata. If the region is entirely outside the crop region, it will be ignored and * not reported in the result metadata.</p> + * <p>When setting the AWB metering regions, the application must consider the additional + * crop resulted from the aspect ratio differences between the preview stream and + * {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}. For example, if the {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} is the full + * active array size with 4:3 aspect ratio, and the preview stream is 16:9, + * the boundary of AWB regions will be [0, y_crop] and + * [active_width, active_height - 2 * y_crop] rather than [0, 0] and + * [active_width, active_height], where y_crop is the additional crop due to aspect ratio + * mismatch.</p> * <p>Starting from API level 30, the coordinate system of activeArraySize or * preCorrectionActiveArraySize is used to represent post-zoomRatio field of view, not * pre-zoom field of view. This means that the same awbRegions values at different diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java index 60d5e9eba3e0..1faec5b76524 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -829,6 +829,14 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * region and output only the intersection rectangle as the metering region in the result * metadata. If the region is entirely outside the crop region, it will be ignored and * not reported in the result metadata.</p> + * <p>When setting the AE metering regions, the application must consider the additional + * crop resulted from the aspect ratio differences between the preview stream and + * {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}. For example, if the {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} is the full + * active array size with 4:3 aspect ratio, and the preview stream is 16:9, + * the boundary of AE regions will be [0, y_crop] and + * [active_width, active_height - 2 * y_crop] rather than [0, 0] and + * [active_width, active_height], where y_crop is the additional crop due to aspect ratio + * mismatch.</p> * <p>Starting from API level 30, the coordinate system of activeArraySize or * preCorrectionActiveArraySize is used to represent post-zoomRatio field of view, not * pre-zoom field of view. This means that the same aeRegions values at different @@ -1301,6 +1309,14 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * region and output only the intersection rectangle as the metering region in the result * metadata. If the region is entirely outside the crop region, it will be ignored and * not reported in the result metadata.</p> + * <p>When setting the AF metering regions, the application must consider the additional + * crop resulted from the aspect ratio differences between the preview stream and + * {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}. For example, if the {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} is the full + * active array size with 4:3 aspect ratio, and the preview stream is 16:9, + * the boundary of AF regions will be [0, y_crop] and + * [active_width, active_height - 2 * y_crop] rather than [0, 0] and + * [active_width, active_height], where y_crop is the additional crop due to aspect ratio + * mismatch.</p> * <p>Starting from API level 30, the coordinate system of activeArraySize or * preCorrectionActiveArraySize is used to represent post-zoomRatio field of view, not * pre-zoom field of view. This means that the same afRegions values at different @@ -1926,6 +1942,14 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * region and output only the intersection rectangle as the metering region in the result * metadata. If the region is entirely outside the crop region, it will be ignored and * not reported in the result metadata.</p> + * <p>When setting the AWB metering regions, the application must consider the additional + * crop resulted from the aspect ratio differences between the preview stream and + * {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}. For example, if the {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} is the full + * active array size with 4:3 aspect ratio, and the preview stream is 16:9, + * the boundary of AWB regions will be [0, y_crop] and + * [active_width, active_height - 2 * y_crop] rather than [0, 0] and + * [active_width, active_height], where y_crop is the additional crop due to aspect ratio + * mismatch.</p> * <p>Starting from API level 30, the coordinate system of activeArraySize or * preCorrectionActiveArraySize is used to represent post-zoomRatio field of view, not * pre-zoom field of view. This means that the same awbRegions values at different diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index 60c4b523094e..28f1f02b7a93 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -45,6 +45,7 @@ import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricFingerprintConstants; import android.hardware.biometrics.BiometricPrompt; +import android.hardware.biometrics.BiometricStateListener; import android.hardware.biometrics.BiometricTestSession; import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; import android.hardware.biometrics.SensorProperties; @@ -918,13 +919,13 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing /** - * Forwards FingerprintStateListener to FingerprintService - * @param listener new FingerprintStateListener being added + * Forwards BiometricStateListener to FingerprintService + * @param listener new BiometricStateListener being added * @hide */ - public void registerFingerprintStateListener(@NonNull FingerprintStateListener listener) { + public void registerBiometricStateListener(@NonNull BiometricStateListener listener) { try { - mService.registerFingerprintStateListener(listener); + mService.registerBiometricStateListener(listener); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl index d60bb6ef1543..0b6344617663 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl @@ -17,13 +17,13 @@ package android.hardware.fingerprint; import android.hardware.biometrics.IBiometricSensorReceiver; import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; +import android.hardware.biometrics.IBiometricStateListener; import android.hardware.biometrics.IInvalidationCallback; import android.hardware.biometrics.ITestSession; import android.hardware.biometrics.ITestSessionCallback; import android.hardware.fingerprint.IFingerprintClientActiveCallback; import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback; import android.hardware.fingerprint.IFingerprintServiceReceiver; -import android.hardware.fingerprint.IFingerprintStateListener; import android.hardware.fingerprint.IUdfpsOverlayController; import android.hardware.fingerprint.ISidefpsController; import android.hardware.fingerprint.Fingerprint; @@ -169,6 +169,6 @@ interface IFingerprintService { // Sets the controller for managing the SideFPS overlay. void setSidefpsController(in ISidefpsController controller); - // Registers FingerprintStateListener in list stored by FingerprintService. - void registerFingerprintStateListener(IFingerprintStateListener listener); + // Registers BiometricStateListener. + void registerBiometricStateListener(IBiometricStateListener listener); } diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 4fdd53425328..6ece5efae537 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -101,6 +101,7 @@ import android.view.BatchedInputEventReceiver.SimpleBatchedInputEventReceiver; import android.view.Choreographer; import android.view.Gravity; import android.view.InputChannel; +import android.view.InputDevice; import android.view.InputEventReceiver; import android.view.KeyCharacterMap; import android.view.KeyEvent; @@ -134,7 +135,10 @@ import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.TextView; +import android.window.OnBackInvokedCallback; +import android.window.OnBackInvokedDispatcher; import android.window.WindowMetricsHelper; +import android.window.WindowOnBackInvokedDispatcher; import com.android.internal.annotations.GuardedBy; import com.android.internal.inputmethod.IInputContentUriToken; @@ -345,6 +349,9 @@ public class InputMethodService extends AbstractInputMethodService { **/ private RingBuffer<MotionEvent> mPendingEvents; + /** Callback to handle back invocation when IME window is shown. */ + private OnBackInvokedCallback mBackCallback; + /** * Returns whether {@link InputMethodService} is responsible for rendering the back button and * the IME switcher button or not when the gestural navigation is enabled. @@ -1605,6 +1612,7 @@ public class InputMethodService extends AbstractInputMethodService { @Override public void onDestroy() { mDestroyed = true; super.onDestroy(); + unregisterOnBackInvokedCallback(); mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener( mInsetsComputer); doFinishInput(); @@ -2579,6 +2587,7 @@ public class InputMethodService extends AbstractInputMethodService { cancelImeSurfaceRemoval(); mInShowWindow = false; Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); + registerOnBackInvokedCallback(); } @@ -2625,6 +2634,56 @@ public class InputMethodService extends AbstractInputMethodService { } /** + * Registers an {@link OnBackInvokedCallback} to handle back invocation when ahead-of-time + * back dispatching is enabled. We keep the KEYCODE_BACK based legacy code around to handle + * back on older devices. + */ + private void registerOnBackInvokedCallback() { + if (mBackCallback != null) { + // A back callback has already been registered. + return; + } + final ViewRootImpl viewRootImpl = mRootView == null ? null : mRootView.getViewRootImpl(); + if (viewRootImpl != null && WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled( + viewRootImpl.mContext)) { + final OnBackInvokedCallback callback = () -> { + KeyEvent downEvent = createKeyEvent( + KeyEvent.ACTION_DOWN, false /* isTracking */); + onKeyDown(KeyEvent.KEYCODE_BACK, downEvent); + boolean hasStartedTracking = + (downEvent.getFlags() & KeyEvent.FLAG_START_TRACKING) != 0; + KeyEvent upEvent = createKeyEvent(KeyEvent.ACTION_UP, hasStartedTracking); + onKeyUp(KeyEvent.KEYCODE_BACK, upEvent); + }; + viewRootImpl.getOnBackInvokedDispatcher().registerOnBackInvokedCallback( + OnBackInvokedDispatcher.PRIORITY_DEFAULT, callback); + mBackCallback = callback; + } + } + + private KeyEvent createKeyEvent(int action, boolean isTracking) { + final long when = SystemClock.uptimeMillis(); + return new KeyEvent(when, when, action, + KeyEvent.KEYCODE_BACK, 0 /* repeat */, 0 /* metaState */, + KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */, + KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY + | (isTracking ? KeyEvent.FLAG_TRACKING : 0), + InputDevice.SOURCE_KEYBOARD); + } + + private void unregisterOnBackInvokedCallback() { + final ViewRootImpl viewRootImpl = mRootView == null ? null : mRootView.getViewRootImpl(); + if (viewRootImpl != null + && mBackCallback != null + && WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled( + viewRootImpl.mContext)) { + viewRootImpl.getOnBackInvokedDispatcher() + .unregisterOnBackInvokedCallback(mBackCallback); + } + mBackCallback = null; + } + + /** * Applies the IME visibility in {@link android.view.ImeInsetsSourceConsumer}. * * @param setVisible {@code true} to make it visible, false to hide it. @@ -2669,6 +2728,7 @@ public class InputMethodService extends AbstractInputMethodService { } mLastWasInFullscreenMode = mIsFullscreen; updateFullscreenMode(); + unregisterOnBackInvokedCallback(); } /** diff --git a/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java index 69e63133eb03..2d1a3fe8e967 100644 --- a/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java +++ b/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java @@ -57,9 +57,11 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork @NonNull private final Set<Integer> mAllowedSpecificCarrierIds; private static final String ROAMING_MATCH_KEY = "mRoamingMatchCriteria"; + private static final int DEFAULT_ROAMING_MATCH_CRITERIA = MATCH_ANY; private final int mRoamingMatchCriteria; private static final String OPPORTUNISTIC_MATCH_KEY = "mOpportunisticMatchCriteria"; + private static final int DEFAULT_OPPORTUNISTIC_MATCH_CRITERIA = MATCH_ANY; private final int mOpportunisticMatchCriteria; private VcnCellUnderlyingNetworkTemplate( @@ -253,23 +255,31 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork /** @hide */ @Override void dumpTransportSpecificFields(IndentingPrintWriter pw) { - pw.println("mAllowedNetworkPlmnIds: " + mAllowedNetworkPlmnIds.toString()); - pw.println("mAllowedSpecificCarrierIds: " + mAllowedSpecificCarrierIds.toString()); - pw.println("mRoamingMatchCriteria: " + getMatchCriteriaString(mRoamingMatchCriteria)); - pw.println( - "mOpportunisticMatchCriteria: " - + getMatchCriteriaString(mOpportunisticMatchCriteria)); + if (!mAllowedNetworkPlmnIds.isEmpty()) { + pw.println("mAllowedNetworkPlmnIds: " + mAllowedNetworkPlmnIds); + } + if (!mAllowedNetworkPlmnIds.isEmpty()) { + pw.println("mAllowedSpecificCarrierIds: " + mAllowedSpecificCarrierIds); + } + if (mRoamingMatchCriteria != DEFAULT_ROAMING_MATCH_CRITERIA) { + pw.println("mRoamingMatchCriteria: " + getMatchCriteriaString(mRoamingMatchCriteria)); + } + if (mOpportunisticMatchCriteria != DEFAULT_OPPORTUNISTIC_MATCH_CRITERIA) { + pw.println( + "mOpportunisticMatchCriteria: " + + getMatchCriteriaString(mOpportunisticMatchCriteria)); + } } /** This class is used to incrementally build VcnCellUnderlyingNetworkTemplate objects. */ public static final class Builder { - private int mMeteredMatchCriteria = MATCH_ANY; + private int mMeteredMatchCriteria = DEFAULT_METERED_MATCH_CRITERIA; @NonNull private final Set<String> mAllowedNetworkPlmnIds = new ArraySet<>(); @NonNull private final Set<Integer> mAllowedSpecificCarrierIds = new ArraySet<>(); - private int mRoamingMatchCriteria = MATCH_ANY; - private int mOpportunisticMatchCriteria = MATCH_ANY; + private int mRoamingMatchCriteria = DEFAULT_ROAMING_MATCH_CRITERIA; + private int mOpportunisticMatchCriteria = DEFAULT_OPPORTUNISTIC_MATCH_CRITERIA; private int mMinEntryUpstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS; private int mMinExitUpstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS; diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java index 390c3b9453c2..f1b110ab29c8 100644 --- a/core/java/android/net/vcn/VcnManager.java +++ b/core/java/android/net/vcn/VcnManager.java @@ -172,11 +172,11 @@ public class VcnManager { * * <p>An app that has carrier privileges for any of the subscriptions in the given group may * clear a VCN configuration. This API is ONLY permitted for callers running as the primary - * user. Any active VCN will be torn down. + * user. Any active VCN associated with this configuration will be torn down. * * @param subscriptionGroup the subscription group that the configuration should be applied to - * @throws SecurityException if the caller does not have carrier privileges, or is not running - * as the primary user + * @throws SecurityException if the caller does not have carrier privileges, is not the owner of + * the associated configuration, or is not running as the primary user * @throws IOException if the configuration failed to be cleared from disk. This may occur due * to temporary disk errors, or more permanent conditions such as a full disk. */ @@ -196,8 +196,13 @@ public class VcnManager { /** * Retrieves the list of Subscription Groups for which a VCN Configuration has been set. * - * <p>The returned list will include only subscription groups for which the carrier app is - * privileged, and which have an associated {@link VcnConfig}. + * <p>The returned list will include only subscription groups for which an associated {@link + * VcnConfig} exists, and the app is either: + * + * <ul> + * <li>Carrier privileged for that subscription group, or + * <li>Is the provisioning package of the config + * </ul> * * @throws SecurityException if the caller is not running as the primary user */ diff --git a/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java index 3a9ca3edded7..9235d0913295 100644 --- a/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java +++ b/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java @@ -15,8 +15,6 @@ */ package android.net.vcn; -import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_ANY; - import static com.android.internal.annotations.VisibleForTesting.Visibility; import android.annotation.IntDef; @@ -88,6 +86,9 @@ public abstract class VcnUnderlyingNetworkTemplate { /** @hide */ static final String METERED_MATCH_KEY = "mMeteredMatchCriteria"; + /** @hide */ + static final int DEFAULT_METERED_MATCH_CRITERIA = MATCH_ANY; + private final int mMeteredMatchCriteria; /** @hide */ @@ -237,11 +238,21 @@ public abstract class VcnUnderlyingNetworkTemplate { pw.println(this.getClass().getSimpleName() + ":"); pw.increaseIndent(); - pw.println("mMeteredMatchCriteria: " + getMatchCriteriaString(mMeteredMatchCriteria)); - pw.println("mMinEntryUpstreamBandwidthKbps: " + mMinEntryUpstreamBandwidthKbps); - pw.println("mMinExitUpstreamBandwidthKbps: " + mMinExitUpstreamBandwidthKbps); - pw.println("mMinEntryDownstreamBandwidthKbps: " + mMinEntryDownstreamBandwidthKbps); - pw.println("mMinExitDownstreamBandwidthKbps: " + mMinExitDownstreamBandwidthKbps); + if (mMeteredMatchCriteria != DEFAULT_METERED_MATCH_CRITERIA) { + pw.println("mMeteredMatchCriteria: " + getMatchCriteriaString(mMeteredMatchCriteria)); + } + if (mMinEntryUpstreamBandwidthKbps != DEFAULT_MIN_BANDWIDTH_KBPS) { + pw.println("mMinEntryUpstreamBandwidthKbps: " + mMinEntryUpstreamBandwidthKbps); + } + if (mMinExitUpstreamBandwidthKbps != DEFAULT_MIN_BANDWIDTH_KBPS) { + pw.println("mMinExitUpstreamBandwidthKbps: " + mMinExitUpstreamBandwidthKbps); + } + if (mMinEntryDownstreamBandwidthKbps != DEFAULT_MIN_BANDWIDTH_KBPS) { + pw.println("mMinEntryDownstreamBandwidthKbps: " + mMinEntryDownstreamBandwidthKbps); + } + if (mMinExitDownstreamBandwidthKbps != DEFAULT_MIN_BANDWIDTH_KBPS) { + pw.println("mMinExitDownstreamBandwidthKbps: " + mMinExitDownstreamBandwidthKbps); + } dumpTransportSpecificFields(pw); pw.decreaseIndent(); diff --git a/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java index 23a07abdf0cb..2544a6d63561 100644 --- a/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java +++ b/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java @@ -147,7 +147,9 @@ public final class VcnWifiUnderlyingNetworkTemplate extends VcnUnderlyingNetwork /** @hide */ @Override void dumpTransportSpecificFields(IndentingPrintWriter pw) { - pw.println("mSsids: " + mSsids); + if (!mSsids.isEmpty()) { + pw.println("mSsids: " + mSsids); + } } /** diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 42e6ac4df8af..0b956f8bf9e0 100755 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -1166,7 +1166,7 @@ public class Build { /** * Tiramisu. */ - public static final int TIRAMISU = CUR_DEVELOPMENT; + public static final int TIRAMISU = 33; } /** The type of build, like "user" or "eng". */ diff --git a/core/java/android/os/IpcDataCache.java b/core/java/android/os/IpcDataCache.java index 0efa34cdc47f..bf44d65c4002 100644 --- a/core/java/android/os/IpcDataCache.java +++ b/core/java/android/os/IpcDataCache.java @@ -23,7 +23,7 @@ import android.annotation.SystemApi; import android.annotation.TestApi; import android.app.PropertyInvalidatedCache; import android.text.TextUtils; -import android.util.Log; +import android.util.ArraySet; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.FastPrintWriter; @@ -35,7 +35,6 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; @@ -324,8 +323,8 @@ public class IpcDataCache<Query, Result> extends PropertyInvalidatedCache<Query, @SystemApi(client=SystemApi.Client.MODULE_LIBRARIES) @TestApi public IpcDataCache(int maxEntries, @NonNull @IpcDataCacheModule String module, - @NonNull String api, - @NonNull String cacheName, @NonNull QueryHandler<Query, Result> computer) { + @NonNull String api, @NonNull String cacheName, + @NonNull QueryHandler<Query, Result> computer) { super(maxEntries, module, api, cacheName, computer); } @@ -382,4 +381,210 @@ public class IpcDataCache<Query, Result> extends PropertyInvalidatedCache<Query, @NonNull String api) { PropertyInvalidatedCache.invalidateCache(module, api); } + + /** + * This is a convenience class that encapsulates configuration information for a + * cache. It may be supplied to the cache constructors in lieu of the other + * parameters. The class captures maximum entry count, the module, the key, and the + * api. + * + * There are three specific use cases supported by this class. + * + * 1. Instance-per-cache: create a static instance of this class using the same + * parameters as would have been given to IpcDataCache (or + * PropertyInvalidatedCache). This static instance provides a hook for the + * invalidateCache() and disableForLocalProcess() calls, which, generally, must + * also be static. + * + * 2. Short-hand for shared configuration parameters: create an instance of this class + * to capture the maximum number of entries and the module to be used by more than + * one cache in the class. Refer to this instance when creating new configs. Only + * the api and (optionally key) for the new cache must be supplied. + * + * 3. Tied caches: create a static instance of this class to capture the maximum + * number of entries, the module, and the key. Refer to this instance when + * creating a new config that differs in only the api. The new config can be + * created as part of the cache constructor. All caches that trace back to the + * root config share the same key and are invalidated by the invalidateCache() + * method of the root config. All caches that trace back to the root config can be + * disabled in the local process by the disableAllForCurrentProcess() method of the + * root config. + * + * @hide + */ + public static class Config { + private final int mMaxEntries; + @IpcDataCacheModule + private final String mModule; + private final String mApi; + private final String mName; + + /** + * The list of cache names that were created extending this Config. If + * disableForCurrentProcess() is invoked on this config then all children will be + * disabled. Furthermore, any new children based off of this config will be + * disabled. The construction order guarantees that new caches will be disabled + * before they are created (the Config must be created before the IpcDataCache is + * created). + */ + private ArraySet<String> mChildren; + + /** + * True if registered children are disabled in the current process. If this is + * true then all new children are disabled as they are registered. + */ + private boolean mDisabled = false; + + public Config(int maxEntries, @NonNull @IpcDataCacheModule String module, + @NonNull String api, @NonNull String name) { + mMaxEntries = maxEntries; + mModule = module; + mApi = api; + mName = name; + } + + /** + * A short-hand constructor that makes the name the same as the api. + */ + public Config(int maxEntries, @NonNull @IpcDataCacheModule String module, + @NonNull String api) { + this(maxEntries, module, api, api); + } + + /** + * Copy the module and max entries from the Config and take the api and name from + * the parameter list. + */ + public Config(@NonNull Config root, @NonNull String api, @NonNull String name) { + this(root.maxEntries(), root.module(), api, name); + } + + /** + * Copy the module and max entries from the Config and take the api and name from + * the parameter list. + */ + public Config(@NonNull Config root, @NonNull String api) { + this(root.maxEntries(), root.module(), api, api); + } + + /** + * Fetch a config that is a child of <this>. The child shares the same api as the + * parent and is registered with the parent for the purposes of disabling in the + * current process. + */ + public Config child(@NonNull String name) { + final Config result = new Config(this, api(), name); + registerChild(name); + return result; + } + + public final int maxEntries() { + return mMaxEntries; + } + + @IpcDataCacheModule + public final @NonNull String module() { + return mModule; + } + + public final @NonNull String api() { + return mApi; + } + + public final @NonNull String name() { + return mName; + } + + /** + * Register a child cache name. If disableForCurrentProcess() has been called + * against this cache, disable th new child. + */ + private final void registerChild(String name) { + synchronized (this) { + if (mChildren == null) { + mChildren = new ArraySet<>(); + } + mChildren.add(name); + if (mDisabled) { + IpcDataCache.disableForCurrentProcess(name); + } + } + } + + /** + * Invalidate all caches that share this Config's module and api. + */ + public void invalidateCache() { + IpcDataCache.invalidateCache(mModule, mApi); + } + + /** + * Disable all caches that share this Config's name. + */ + public void disableForCurrentProcess() { + IpcDataCache.disableForCurrentProcess(mName); + } + + /** + * Disable this cache and all children. Any child that is added in the future + * will alwo be disabled. + */ + public void disableAllForCurrentProcess() { + synchronized (this) { + mDisabled = true; + disableForCurrentProcess(); + if (mChildren != null) { + for (String c : mChildren) { + IpcDataCache.disableForCurrentProcess(c); + } + } + } + } + } + + /** + * Create a new cache using a config. + * @hide + */ + public IpcDataCache(@NonNull Config config, @NonNull QueryHandler<Query, Result> computer) { + super(config.maxEntries(), config.module(), config.api(), config.name(), computer); + } + + /** + * An interface suitable for a lambda expression instead of a QueryHandler. + * @hide + */ + public interface RemoteCall<Query, Result> { + Result apply(Query query) throws RemoteException; + } + + /** + * This is a query handler that is created with a lambda expression that is invoked + * every time the handler is called. The handler is specifically meant for services + * hosted by system_server; the handler automatically rethrows RemoteException as a + * RuntimeException, which is the usual handling for failed binder calls. + */ + private static class SystemServerCallHandler<Query, Result> + extends IpcDataCache.QueryHandler<Query, Result> { + private final RemoteCall<Query, Result> mHandler; + public SystemServerCallHandler(RemoteCall handler) { + mHandler = handler; + } + @Override + public Result apply(Query query) { + try { + return mHandler.apply(query); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + + /** + * Create a cache using a config and a lambda expression. + * @hide + */ + public IpcDataCache(@NonNull Config config, @NonNull RemoteCall<Query, Result> computer) { + this(config, new SystemServerCallHandler<>(computer)); + } } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 0df4f5feef50..d4ce21eef794 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2013,6 +2013,15 @@ public final class Settings { "android.settings.ALL_APPS_NOTIFICATION_SETTINGS"; /** + * Activity Action: Show app settings specifically for sending notifications. Same as + * ALL_APPS_NOTIFICATION_SETTINGS but meant for internal use. + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_ALL_APPS_NOTIFICATION_SETTINGS_FOR_REVIEW = + "android.settings.ALL_APPS_NOTIFICATION_SETTINGS_FOR_REVIEW"; + + /** * Activity Action: Show notification settings for a single app. * <p> * Input: {@link #EXTRA_APP_PACKAGE}, the package to display. @@ -4519,13 +4528,6 @@ public final class Settings { public static final String SCREEN_OFF_TIMEOUT = "screen_off_timeout"; /** - * The amount of time in milliseconds before the device goes to sleep or begins to dream - * after a period of inactivity while it is docked. - * @hide - */ - public static final String SCREEN_OFF_TIMEOUT_DOCKED = "screen_off_timeout_docked"; - - /** * The screen backlight brightness between 0 and 255. */ @Readable @@ -7677,6 +7679,20 @@ public final class Settings { "zen_settings_suggestion_viewed"; /** + * State of whether review notification permissions notification needs to + * be shown the user, and whether the user has interacted. + * + * Valid values: + * -1 = UNKNOWN + * 0 = SHOULD_SHOW + * 1 = USER_INTERACTED + * 2 = DISMISSED + * @hide + */ + public static final String REVIEW_PERMISSIONS_NOTIFICATION_STATE = + "review_permissions_notification_state"; + + /** * Whether the in call notification is enabled to play sound during calls. The value is * boolean (1 or 0). * @hide diff --git a/core/java/android/service/dreams/DreamActivity.java b/core/java/android/service/dreams/DreamActivity.java index 96bbf8ebc2cb..cf4e6a6da96e 100644 --- a/core/java/android/service/dreams/DreamActivity.java +++ b/core/java/android/service/dreams/DreamActivity.java @@ -19,6 +19,7 @@ package android.service.dreams; import android.annotation.Nullable; import android.app.Activity; import android.os.Bundle; +import android.text.TextUtils; import com.android.internal.R; @@ -44,6 +45,7 @@ import com.android.internal.R; */ public class DreamActivity extends Activity { static final String EXTRA_CALLBACK = "binder"; + static final String EXTRA_DREAM_TITLE = "title"; public DreamActivity() {} @@ -51,6 +53,11 @@ public class DreamActivity extends Activity { public void onCreate(@Nullable Bundle bundle) { super.onCreate(bundle); + final String title = getIntent().getStringExtra(EXTRA_DREAM_TITLE); + if (!TextUtils.isEmpty(title)) { + setTitle(title); + } + DreamService.DreamServiceWrapper callback = (DreamService.DreamServiceWrapper) getIntent().getIBinderExtra(EXTRA_CALLBACK); diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java index d4f8a3beb89b..95eae6cada9f 100644 --- a/core/java/android/service/dreams/DreamService.java +++ b/core/java/android/service/dreams/DreamService.java @@ -1280,6 +1280,9 @@ public class DreamService extends Service implements Window.Callback { i.setPackage(getApplicationContext().getPackageName()); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i.putExtra(DreamActivity.EXTRA_CALLBACK, mDreamServiceWrapper); + final ServiceInfo serviceInfo = fetchServiceInfo(this, + new ComponentName(this, getClass())); + i.putExtra(DreamActivity.EXTRA_DREAM_TITLE, fetchDreamLabel(this, serviceInfo)); try { if (!ActivityTaskManager.getService().startDreamActivity(i)) { diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java index 0829d2813c83..85502197ea7e 100644 --- a/core/java/android/service/quicksettings/TileService.java +++ b/core/java/android/service/quicksettings/TileService.java @@ -353,7 +353,13 @@ public class TileService extends Service { try { mTile = mService.getTile(mTileToken); } catch (RemoteException e) { - throw new RuntimeException("Unable to reach IQSService", e); + String name = TileService.this.getClass().getSimpleName(); + Log.w(TAG, name + " - Couldn't get tile from IQSService.", e); + // If we couldn't receive the tile, there's not much reason to continue as users won't + // be able to interact. Returning `null` will trigger an unbind in SystemUI and + // eventually we'll rebind when needed. This usually means that SystemUI crashed + // right after binding and therefore `mService` is outdated. + return null; } if (mTile != null) { mTile.setService(mService, mTileToken); diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 5131e4e58f54..425dbb9cb204 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -1685,13 +1685,12 @@ public abstract class WallpaperService extends Service { void updatePage(EngineWindowPage currentPage, int pageIndx, int numPages, float xOffsetStep) { - // to save creating a runnable, check twice - long current = System.currentTimeMillis(); + // in case the clock is zero, we start with negative time + long current = SystemClock.elapsedRealtime() - DEFAULT_UPDATE_SCREENSHOT_DURATION; long lapsed = current - currentPage.getLastUpdateTime(); // Always update the page when the last update time is <= 0 // This is important especially when the device first boots - if (lapsed < DEFAULT_UPDATE_SCREENSHOT_DURATION - && currentPage.getLastUpdateTime() > 0) { + if (lapsed < DEFAULT_UPDATE_SCREENSHOT_DURATION) { return; } Surface surface = mSurfaceHolder.getSurface(); diff --git a/core/java/android/transparency/OWNERS b/core/java/android/transparency/OWNERS index 75bf84c727df..ed0e5e5f36ad 100644 --- a/core/java/android/transparency/OWNERS +++ b/core/java/android/transparency/OWNERS @@ -1,4 +1,5 @@ -# Bug component: 36824 +# Bug component: 1164579 billylau@google.com -vishwath@google.com mpgroover@google.com +vishwath@google.com +wenhaowang@google.com diff --git a/core/java/android/view/AccessibilityEmbeddedConnection.java b/core/java/android/view/AccessibilityEmbeddedConnection.java index de895d9c2e8e..a7d3164198a1 100644 --- a/core/java/android/view/AccessibilityEmbeddedConnection.java +++ b/core/java/android/view/AccessibilityEmbeddedConnection.java @@ -33,7 +33,7 @@ import java.lang.ref.WeakReference; */ final class AccessibilityEmbeddedConnection extends IAccessibilityEmbeddedConnection.Stub { private final WeakReference<ViewRootImpl> mViewRootImpl; - private final Matrix mTmpScreenMatrix = new Matrix(); + private final Matrix mTmpWindowMatrix = new Matrix(); AccessibilityEmbeddedConnection(ViewRootImpl viewRootImpl) { mViewRootImpl = new WeakReference<>(viewRootImpl); @@ -70,14 +70,14 @@ final class AccessibilityEmbeddedConnection extends IAccessibilityEmbeddedConnec } @Override - public void setScreenMatrix(float[] matrixValues) { + public void setWindowMatrix(float[] matrixValues) { final ViewRootImpl viewRootImpl = mViewRootImpl.get(); if (viewRootImpl != null) { - mTmpScreenMatrix.setValues(matrixValues); - if (viewRootImpl.mAttachInfo.mScreenMatrixInEmbeddedHierarchy == null) { - viewRootImpl.mAttachInfo.mScreenMatrixInEmbeddedHierarchy = new Matrix(); + mTmpWindowMatrix.setValues(matrixValues); + if (viewRootImpl.mAttachInfo.mWindowMatrixInEmbeddedHierarchy == null) { + viewRootImpl.mAttachInfo.mWindowMatrixInEmbeddedHierarchy = new Matrix(); } - viewRootImpl.mAttachInfo.mScreenMatrixInEmbeddedHierarchy.set(mTmpScreenMatrix); + viewRootImpl.mAttachInfo.mWindowMatrixInEmbeddedHierarchy.set(mTmpWindowMatrix); } } } diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java index 7e0b79470cf2..23e1505e1a4c 100644 --- a/core/java/android/view/AccessibilityInteractionController.java +++ b/core/java/android/view/AccessibilityInteractionController.java @@ -22,7 +22,6 @@ import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_REQUES import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY; import android.graphics.Matrix; -import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; @@ -112,10 +111,7 @@ public final class AccessibilityInteractionController { private final ArrayList<View> mTempArrayList = new ArrayList<View>(); - private final Point mTempPoint = new Point(); private final Rect mTempRect = new Rect(); - private final Rect mTempRect1 = new Rect(); - private final Rect mTempRect2 = new Rect(); private final RectF mTempRectF = new RectF(); private AddNodeInfosForViewId mAddNodeInfosForViewId; @@ -131,7 +127,7 @@ public final class AccessibilityInteractionController { private int mActiveRequestPreparerId; public AccessibilityInteractionController(ViewRootImpl viewRootImpl) { - Looper looper = viewRootImpl.mHandler.getLooper(); + Looper looper = viewRootImpl.mHandler.getLooper(); mMyLooperThreadId = looper.getThread().getId(); mMyProcessId = Process.myPid(); mHandler = new PrivateHandler(looper); @@ -173,7 +169,8 @@ public final class AccessibilityInteractionController { public void findAccessibilityNodeInfoByAccessibilityIdClientThread( long accessibilityNodeId, Region interactiveRegion, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, - long interrogatingTid, MagnificationSpec spec, Bundle arguments) { + long interrogatingTid, MagnificationSpec spec, float[] matrixValues, + Bundle arguments) { final Message message = mHandler.obtainMessage(); message.what = PrivateHandler.MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID; message.arg1 = flags; @@ -186,6 +183,7 @@ public final class AccessibilityInteractionController { args.arg2 = spec; args.arg3 = interactiveRegion; args.arg4 = arguments; + args.arg5 = matrixValues; message.obj = args; synchronized (mLock) { @@ -344,6 +342,7 @@ public final class AccessibilityInteractionController { final MagnificationSpec spec = (MagnificationSpec) args.arg2; final Region interactiveRegion = (Region) args.arg3; final Bundle arguments = (Bundle) args.arg4; + final float[] matrixValues = (float[]) args.arg5; args.recycle(); @@ -378,7 +377,7 @@ public final class AccessibilityInteractionController { if (!interruptPrefetch) { // Return found node and prefetched nodes in one IPC. updateInfosForViewportAndReturnFindNodeResult(infos, callback, interactionId, spec, - interactiveRegion); + matrixValues, interactiveRegion); final SatisfiedFindAccessibilityNodeByAccessibilityIdRequest satisfiedRequest = getSatisfiedRequestInPrefetch(requestedNode == null ? null : requestedNode, @@ -391,13 +390,13 @@ public final class AccessibilityInteractionController { // Return found node. updateInfoForViewportAndReturnFindNodeResult( requestedNode == null ? null : new AccessibilityNodeInfo(requestedNode), - callback, interactionId, spec, interactiveRegion); + callback, interactionId, spec, matrixValues, interactiveRegion); } } mPrefetcher.prefetchAccessibilityNodeInfos(requestedView, requestedNode == null ? null : new AccessibilityNodeInfo(requestedNode), infos); mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; - updateInfosForViewPort(infos, spec, interactiveRegion); + updateInfosForViewPort(infos, spec, matrixValues, interactiveRegion); final SatisfiedFindAccessibilityNodeByAccessibilityIdRequest satisfiedRequest = getSatisfiedRequestInPrefetch(requestedNode == null ? null : requestedNode, infos, flags); @@ -439,7 +438,7 @@ public final class AccessibilityInteractionController { public void findAccessibilityNodeInfosByViewIdClientThread(long accessibilityNodeId, String viewId, Region interactiveRegion, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, - long interrogatingTid, MagnificationSpec spec) { + long interrogatingTid, MagnificationSpec spec, float[] matrixValues) { Message message = mHandler.obtainMessage(); message.what = PrivateHandler.MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID; message.arg1 = flags; @@ -451,6 +450,7 @@ public final class AccessibilityInteractionController { args.arg2 = spec; args.arg3 = viewId; args.arg4 = interactiveRegion; + args.arg5 = matrixValues; message.obj = args; scheduleMessage(message, interrogatingPid, interrogatingTid, CONSIDER_REQUEST_PREPARERS); @@ -467,6 +467,7 @@ public final class AccessibilityInteractionController { final MagnificationSpec spec = (MagnificationSpec) args.arg2; final String viewId = (String) args.arg3; final Region interactiveRegion = (Region) args.arg4; + final float[] matrixValues = (float[]) args.arg5; args.recycle(); final List<AccessibilityNodeInfo> infos = mTempAccessibilityNodeInfoList; @@ -494,14 +495,14 @@ public final class AccessibilityInteractionController { } finally { mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; updateInfosForViewportAndReturnFindNodeResult( - infos, callback, interactionId, spec, interactiveRegion); + infos, callback, interactionId, spec, matrixValues, interactiveRegion); } } public void findAccessibilityNodeInfosByTextClientThread(long accessibilityNodeId, String text, Region interactiveRegion, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, - long interrogatingTid, MagnificationSpec spec) { + long interrogatingTid, MagnificationSpec spec, float[] matrixValues) { Message message = mHandler.obtainMessage(); message.what = PrivateHandler.MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT; message.arg1 = flags; @@ -514,6 +515,7 @@ public final class AccessibilityInteractionController { args.argi2 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId); args.argi3 = interactionId; args.arg4 = interactiveRegion; + args.arg5 = matrixValues; message.obj = args; scheduleMessage(message, interrogatingPid, interrogatingTid, CONSIDER_REQUEST_PREPARERS); @@ -531,6 +533,7 @@ public final class AccessibilityInteractionController { final int virtualDescendantId = args.argi2; final int interactionId = args.argi3; final Region interactiveRegion = (Region) args.arg4; + final float[] matrixValues = (float[]) args.arg5; args.recycle(); List<AccessibilityNodeInfo> infos = null; @@ -577,14 +580,14 @@ public final class AccessibilityInteractionController { } finally { mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; updateInfosForViewportAndReturnFindNodeResult( - infos, callback, interactionId, spec, interactiveRegion); + infos, callback, interactionId, spec, matrixValues, interactiveRegion); } } public void findFocusClientThread(long accessibilityNodeId, int focusType, Region interactiveRegion, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, - long interrogatingTid, MagnificationSpec spec) { + long interrogatingTid, MagnificationSpec spec, float[] matrixValues) { Message message = mHandler.obtainMessage(); message.what = PrivateHandler.MSG_FIND_FOCUS; message.arg1 = flags; @@ -597,7 +600,7 @@ public final class AccessibilityInteractionController { args.arg1 = callback; args.arg2 = spec; args.arg3 = interactiveRegion; - + args.arg4 = matrixValues; message.obj = args; scheduleMessage(message, interrogatingPid, interrogatingTid, CONSIDER_REQUEST_PREPARERS); @@ -615,6 +618,7 @@ public final class AccessibilityInteractionController { (IAccessibilityInteractionConnectionCallback) args.arg1; final MagnificationSpec spec = (MagnificationSpec) args.arg2; final Region interactiveRegion = (Region) args.arg3; + final float[] matrixValues = (float[]) args.arg4; args.recycle(); AccessibilityNodeInfo focused = null; @@ -672,14 +676,14 @@ public final class AccessibilityInteractionController { } finally { mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; updateInfoForViewportAndReturnFindNodeResult( - focused, callback, interactionId, spec, interactiveRegion); + focused, callback, interactionId, spec, matrixValues, interactiveRegion); } } public void focusSearchClientThread(long accessibilityNodeId, int direction, Region interactiveRegion, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, - long interrogatingTid, MagnificationSpec spec) { + long interrogatingTid, MagnificationSpec spec, float[] matrixValues) { Message message = mHandler.obtainMessage(); message.what = PrivateHandler.MSG_FOCUS_SEARCH; message.arg1 = flags; @@ -691,6 +695,7 @@ public final class AccessibilityInteractionController { args.arg1 = callback; args.arg2 = spec; args.arg3 = interactiveRegion; + args.arg4 = matrixValues; message.obj = args; @@ -708,7 +713,7 @@ public final class AccessibilityInteractionController { (IAccessibilityInteractionConnectionCallback) args.arg1; final MagnificationSpec spec = (MagnificationSpec) args.arg2; final Region interactiveRegion = (Region) args.arg3; - + final float[] matrixValues = (float[]) args.arg4; args.recycle(); AccessibilityNodeInfo next = null; @@ -727,7 +732,7 @@ public final class AccessibilityInteractionController { } finally { mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; updateInfoForViewportAndReturnFindNodeResult( - next, callback, interactionId, spec, interactiveRegion); + next, callback, interactionId, spec, matrixValues, interactiveRegion); } } @@ -882,13 +887,20 @@ public final class AccessibilityInteractionController { } } + // The boundInScreen includes magnification effect, so we need to normalize it before + // determine the visibility. private void adjustIsVisibleToUserIfNeeded(AccessibilityNodeInfo info, - Region interactiveRegion) { + Region interactiveRegion, MagnificationSpec spec) { if (interactiveRegion == null || info == null) { return; } Rect boundsInScreen = mTempRect; info.getBoundsInScreen(boundsInScreen); + if (spec != null && !spec.isNop()) { + boundsInScreen.offset((int) -spec.offsetX, (int) -spec.offsetY); + boundsInScreen.scale(1 / spec.scale); + } + if (interactiveRegion.quickReject(boundsInScreen) && !shouldBypassAdjustIsVisible()) { info.setVisibleToUser(false); } @@ -902,36 +914,30 @@ public final class AccessibilityInteractionController { return false; } - private void applyScreenMatrixIfNeeded(List<AccessibilityNodeInfo> infos) { - if (infos == null || shouldBypassApplyScreenMatrix()) { - return; - } - final int infoCount = infos.size(); - for (int i = 0; i < infoCount; i++) { - final AccessibilityNodeInfo info = infos.get(i); - applyScreenMatrixIfNeeded(info); - } - } - - private void applyScreenMatrixIfNeeded(AccessibilityNodeInfo info) { - if (info == null || shouldBypassApplyScreenMatrix()) { + /** + * Applies the host-window matrix to the embedded node. After this transform, The node bounds + * will be transformed from embedded window coordinates to host-window coordinates. + * + */ + private void applyHostWindowMatrixIfNeeded(AccessibilityNodeInfo info) { + if (info == null || shouldBypassApplyWindowMatrix()) { return; } final Rect boundsInScreen = mTempRect; final RectF transformedBounds = mTempRectF; - final Matrix screenMatrix = mViewRootImpl.mAttachInfo.mScreenMatrixInEmbeddedHierarchy; + final Matrix windowMatrix = mViewRootImpl.mAttachInfo.mWindowMatrixInEmbeddedHierarchy; info.getBoundsInScreen(boundsInScreen); transformedBounds.set(boundsInScreen); - screenMatrix.mapRect(transformedBounds); + windowMatrix.mapRect(transformedBounds); boundsInScreen.set((int) transformedBounds.left, (int) transformedBounds.top, (int) transformedBounds.right, (int) transformedBounds.bottom); info.setBoundsInScreen(boundsInScreen); } - private boolean shouldBypassApplyScreenMatrix() { - final Matrix screenMatrix = mViewRootImpl.mAttachInfo.mScreenMatrixInEmbeddedHierarchy; - return screenMatrix == null || screenMatrix.isIdentity(); + private boolean shouldBypassApplyWindowMatrix() { + final Matrix windowMatrix = mViewRootImpl.mAttachInfo.mWindowMatrixInEmbeddedHierarchy; + return windowMatrix == null || windowMatrix.isIdentity(); } private void associateLeashedParentIfNeeded(AccessibilityNodeInfo info) { @@ -963,46 +969,17 @@ public final class AccessibilityInteractionController { if (!shouldApplyAppScaleAndMagnificationSpec(applicationScale, spec)) { return; } - Rect boundsInParent = mTempRect; - Rect boundsInScreen = mTempRect1; info.getBoundsInParent(boundsInParent); - info.getBoundsInScreen(boundsInScreen); if (applicationScale != 1.0f) { boundsInParent.scale(applicationScale); - boundsInScreen.scale(applicationScale); } if (spec != null) { boundsInParent.scale(spec.scale); // boundsInParent must not be offset. - boundsInScreen.scale(spec.scale); - boundsInScreen.offset((int) spec.offsetX, (int) spec.offsetY); } info.setBoundsInParent(boundsInParent); - info.setBoundsInScreen(boundsInScreen); - - // Scale text locations if they are present - if (info.hasExtras()) { - Bundle extras = info.getExtras(); - Parcelable[] textLocations = - extras.getParcelableArray(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY); - if (textLocations != null) { - for (int i = 0; i < textLocations.length; i++) { - // Unchecked cast - an app that puts other objects in this bundle with this - // key will crash. - RectF textLocation = ((RectF) textLocations[i]); - if (textLocation == null) { - continue; - } - textLocation.scale(applicationScale); - if (spec != null) { - textLocation.scale(spec.scale); - textLocation.offset(spec.offsetX, spec.offsetY); - } - } - } - } } private boolean shouldApplyAppScaleAndMagnificationSpec(float appScale, @@ -1011,27 +988,88 @@ public final class AccessibilityInteractionController { } private void updateInfosForViewPort(List<AccessibilityNodeInfo> infos, MagnificationSpec spec, - Region interactiveRegion) { + float[] matrixValues, Region interactiveRegion) { for (int i = 0; i < infos.size(); i++) { - updateInfoForViewPort(infos.get(i), spec, interactiveRegion); + updateInfoForViewPort(infos.get(i), spec, matrixValues, interactiveRegion); } } private void updateInfoForViewPort(AccessibilityNodeInfo info, MagnificationSpec spec, - Region interactiveRegion) { + float[] matrixValues, Region interactiveRegion) { associateLeashedParentIfNeeded(info); - applyScreenMatrixIfNeeded(info); - // To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node, - // then impact the visibility result, we need to adjust visibility before apply scale. - adjustIsVisibleToUserIfNeeded(info, interactiveRegion); + + applyHostWindowMatrixIfNeeded(info); + // Transform view bounds from window coordinates to screen coordinates. + transformBoundsWithScreenMatrix(info, matrixValues); + adjustIsVisibleToUserIfNeeded(info, interactiveRegion, spec); applyAppScaleAndMagnificationSpecIfNeeded(info, spec); } + + /** + * Transforms the regions from local screen coordinate to global screen coordinate with the + * given transform matrix used in on-screen coordinate. + * + * @param info the AccessibilityNodeInfo that has the region in application screen coordinate + * @param matrixValues the matrix to be applied + */ + private void transformBoundsWithScreenMatrix(AccessibilityNodeInfo info, + float[] matrixValues) { + if (info == null || matrixValues == null) { + return; + } + final Rect boundInScreen = mTempRect; + final RectF transformedBounds = mTempRectF; + + info.getBoundsInScreen(boundInScreen); + transformedBounds.set(boundInScreen); + + final Matrix transformMatrix = new Matrix(); + transformMatrix.setValues(matrixValues); + final float applicationScale = mViewRootImpl.mAttachInfo.mApplicationScale; + if (applicationScale != 1f) { + transformMatrix.preScale(applicationScale, applicationScale); + } + // Transform the bounds from application screen coordinates to global window coordinates. + // For the embedded node, the bounds we get is already in window coordinates, so we don't + // need to do it. + if (mViewRootImpl.mAttachInfo.mWindowMatrixInEmbeddedHierarchy == null) { + transformMatrix.preTranslate(-mViewRootImpl.mAttachInfo.mWindowLeft, + -mViewRootImpl.mAttachInfo.mWindowTop); + } + + if (transformMatrix.isIdentity()) { + return; + } + transformMatrix.mapRect(transformedBounds); + // Offset 0.5f to round after casting. + transformedBounds.offset(0.5f, 0.5f); + boundInScreen.set((int) (transformedBounds.left), (int) transformedBounds.top, + (int) transformedBounds.right, (int) transformedBounds.bottom); + info.setBoundsInScreen(boundInScreen); + // Scale text locations if they are present + if (info.hasExtras()) { + final Bundle extras = info.getExtras(); + final RectF[] textLocations = + extras.getParcelableArray(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY, RectF.class); + if (textLocations != null) { + for (int i = 0; i < textLocations.length; i++) { + // Unchecked cast - an app that puts other objects in this bundle with this + // key will crash. + final RectF textLocation = textLocations[i]; + if (textLocation != null) { + transformMatrix.mapRect(textLocation); + } + } + } + } + } + private void updateInfosForViewportAndReturnFindNodeResult(List<AccessibilityNodeInfo> infos, IAccessibilityInteractionConnectionCallback callback, int interactionId, - MagnificationSpec spec, Region interactiveRegion) { + MagnificationSpec spec, float[] matrixValues, Region interactiveRegion) { if (infos != null) { - updateInfosForViewPort(infos, spec, interactiveRegion); + updateInfosForViewPort(infos, spec, matrixValues, interactiveRegion); } returnFindNodesResult(infos, callback, interactionId); } @@ -1141,8 +1179,8 @@ public final class AccessibilityInteractionController { private void updateInfoForViewportAndReturnFindNodeResult(AccessibilityNodeInfo info, IAccessibilityInteractionConnectionCallback callback, int interactionId, - MagnificationSpec spec, Region interactiveRegion) { - updateInfoForViewPort(info, spec, interactiveRegion); + MagnificationSpec spec, float[] matrixValues, Region interactiveRegion) { + updateInfoForViewPort(info, spec, matrixValues, interactiveRegion); returnFindNodeResult(info, callback, interactionId); } diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 7b6a0d64f980..cce3e8c84451 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -833,10 +833,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } /** - * @see InsetsState#calculateVisibleInsets(Rect, int) + * @see InsetsState#calculateVisibleInsets(Rect, int, int, int, int) */ - public Insets calculateVisibleInsets(@SoftInputModeFlags int softInputMode) { - return mState.calculateVisibleInsets(mFrame, softInputMode); + public Insets calculateVisibleInsets(int windowType, int windowingMode, + @SoftInputModeFlags int softInputMode, int windowFlags) { + return mState.calculateVisibleInsets(mFrame, windowType, windowingMode, softInputMode, + windowFlags); } /** diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java index b1b630ed7353..eb746080de15 100644 --- a/core/java/android/view/InsetsState.java +++ b/core/java/android/view/InsetsState.java @@ -23,11 +23,11 @@ import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE; import static android.view.WindowInsets.Type.displayCutout; import static android.view.WindowInsets.Type.ime; import static android.view.WindowInsets.Type.indexOf; -import static android.view.WindowInsets.Type.isVisibleInsetsType; import static android.view.WindowInsets.Type.statusBars; import static android.view.WindowInsets.Type.systemBars; import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; +import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; @@ -257,7 +257,7 @@ public class InsetsState implements Parcelable { if ((legacyWindowFlags & FLAG_FULLSCREEN) != 0) { compatInsetsTypes &= ~statusBars(); } - if (clearCompatInsets(windowType, legacyWindowFlags, windowingMode)) { + if (clearsCompatInsets(windowType, legacyWindowFlags, windowingMode)) { compatInsetsTypes = 0; } @@ -358,17 +358,23 @@ public class InsetsState implements Parcelable { return insets; } - public Insets calculateVisibleInsets(Rect frame, @SoftInputModeFlags int softInputMode) { + public Insets calculateVisibleInsets(Rect frame, int windowType, int windowingMode, + @SoftInputModeFlags int softInputMode, int windowFlags) { + if (clearsCompatInsets(windowType, windowFlags, windowingMode)) { + return Insets.NONE; + } + final int softInputAdjustMode = softInputMode & SOFT_INPUT_MASK_ADJUST; + final int visibleInsetsTypes = softInputAdjustMode != SOFT_INPUT_ADJUST_NOTHING + ? systemBars() | ime() + : systemBars(); Insets insets = Insets.NONE; for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) { InsetsSource source = mSources[type]; if (source == null) { continue; } - - // Ignore everything that's not a system bar or IME. - int publicType = InsetsState.toPublicType(type); - if (!isVisibleInsetsType(publicType, softInputMode)) { + final int publicType = InsetsState.toPublicType(type); + if ((publicType & visibleInsetsTypes) == 0) { continue; } insets = Insets.max(source.calculateVisibleInsets(frame), insets); @@ -676,7 +682,7 @@ public class InsetsState implements Parcelable { mSources[source.getType()] = source; } - public static boolean clearCompatInsets(int windowType, int windowFlags, int windowingMode) { + public static boolean clearsCompatInsets(int windowType, int windowFlags, int windowingMode) { return (windowFlags & FLAG_LAYOUT_NO_LIMITS) != 0 && windowType != TYPE_WALLPAPER && windowType != TYPE_SYSTEM_ERROR && !WindowConfiguration.inMultiWindowMode(windowingMode); diff --git a/core/java/android/view/RemoteAccessibilityController.java b/core/java/android/view/RemoteAccessibilityController.java index bc0fab1bcf8d..8855fb584ef3 100644 --- a/core/java/android/view/RemoteAccessibilityController.java +++ b/core/java/android/view/RemoteAccessibilityController.java @@ -28,7 +28,7 @@ class RemoteAccessibilityController { private static final String TAG = "RemoteAccessibilityController"; private int mHostId; private RemoteAccessibilityEmbeddedConnection mConnectionWrapper; - private Matrix mScreenMatrixForEmbeddedHierarchy = new Matrix(); + private Matrix mWindowMatrixForEmbeddedHierarchy = new Matrix(); private final float[] mMatrixValues = new float[9]; private View mHostView; @@ -140,9 +140,9 @@ class RemoteAccessibilityController { return mConnectionWrapper; } - void setScreenMatrix(Matrix m) { - // If the screen matrix is identity or doesn't change, do nothing. - if (m.isIdentity() || m.equals(mScreenMatrixForEmbeddedHierarchy)) { + void setWindowMatrix(Matrix m) { + // If the window matrix is identity or doesn't change, do nothing. + if (m.isIdentity() || m.equals(mWindowMatrixForEmbeddedHierarchy)) { return; } @@ -153,8 +153,8 @@ class RemoteAccessibilityController { return; } m.getValues(mMatrixValues); - wrapper.getConnection().setScreenMatrix(mMatrixValues); - mScreenMatrixForEmbeddedHierarchy.set(m); + wrapper.getConnection().setWindowMatrix(mMatrixValues); + mWindowMatrixForEmbeddedHierarchy.set(m); } catch (RemoteException e) { Log.d(TAG, "Error while setScreenMatrix " + e); } diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index ed57136b1d35..96b1abb62dbf 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -967,7 +967,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall final boolean redrawNeeded = sizeChanged || creating || hintChanged || (mVisible && !mDrawFinished); boolean shouldSyncBuffer = - redrawNeeded && viewRoot.wasRelayoutRequested() && viewRoot.isInSync(); + redrawNeeded && viewRoot.wasRelayoutRequested() && viewRoot.isInLocalSync(); SyncBufferTransactionCallback syncBufferTransactionCallback = null; if (shouldSyncBuffer) { syncBufferTransactionCallback = new SyncBufferTransactionCallback(); @@ -1274,6 +1274,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall private class SurfaceViewPositionUpdateListener implements RenderNode.PositionUpdateListener { private final int mRtSurfaceWidth; private final int mRtSurfaceHeight; + private boolean mRtFirst = true; private final SurfaceControl.Transaction mPositionChangedTransaction = new SurfaceControl.Transaction(); @@ -1284,14 +1285,15 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall @Override public void positionChanged(long frameNumber, int left, int top, int right, int bottom) { - if (mRTLastReportedPosition.left == left + if (!mRtFirst && (mRTLastReportedPosition.left == left && mRTLastReportedPosition.top == top && mRTLastReportedPosition.right == right && mRTLastReportedPosition.bottom == bottom && mRTLastReportedSurfaceSize.x == mRtSurfaceWidth - && mRTLastReportedSurfaceSize.y == mRtSurfaceHeight) { + && mRTLastReportedSurfaceSize.y == mRtSurfaceHeight)) { return; } + mRtFirst = false; try { if (DEBUG_POSITION) { Log.d(TAG, String.format( @@ -1781,11 +1783,16 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall return; } getBoundsOnScreen(mTmpRect); + + // To compute the node bounds of the node on the embedded window, + // apply this matrix to get the bounds in host window-relative coordinates, + // then using the global transform to get the actual bounds on screen. + mTmpRect.offset(-mAttachInfo.mWindowLeft, -mAttachInfo.mWindowTop); mTmpMatrix.reset(); mTmpMatrix.setTranslate(mTmpRect.left, mTmpRect.top); mTmpMatrix.postScale(mScreenRect.width() / (float) mSurfaceWidth, mScreenRect.height() / (float) mSurfaceHeight); - mRemoteAccessibilityController.setScreenMatrix(mTmpMatrix); + mRemoteAccessibilityController.setWindowMatrix(mTmpMatrix); } @Override diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 8b9a86b9eec6..569461e81111 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -29938,10 +29938,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, boolean mHandlingPointerEvent; /** - * The screen matrix of this view when it's on a {@link SurfaceControlViewHost} that is + * The window matrix of this view when it's on a {@link SurfaceControlViewHost} that is * embedded within a SurfaceView. */ - Matrix mScreenMatrixInEmbeddedHierarchy; + Matrix mWindowMatrixInEmbeddedHierarchy; /** * Global to the view hierarchy used as a temporary for dealing with diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index a3d0bf79416b..27ce71155857 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -319,6 +319,8 @@ public final class ViewRootImpl implements ViewParent, */ private static final int SCROLL_CAPTURE_REQUEST_TIMEOUT_MILLIS = 2500; + private static final int UNSET_SYNC_ID = -1; + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) static final ThreadLocal<HandlerActionQueue> sRunQueues = new ThreadLocal<HandlerActionQueue>(); @@ -815,7 +817,7 @@ public final class ViewRootImpl implements ViewParent, } private final SurfaceSyncer mSurfaceSyncer = new SurfaceSyncer(); - private int mLastSyncId = -1; + private int mSyncId = UNSET_SYNC_ID; private SurfaceSyncer.SyncBufferCallback mSyncBufferCallback; private int mNumSyncsInProgress = 0; @@ -2570,7 +2572,8 @@ public final class ViewRootImpl implements ViewParent, mAttachInfo.mContentInsets.set(mLastWindowInsets.getSystemWindowInsets().toRect()); mAttachInfo.mStableInsets.set(mLastWindowInsets.getStableInsets().toRect()); mAttachInfo.mVisibleInsets.set(mInsetsController.calculateVisibleInsets( - mWindowAttributes.softInputMode).toRect()); + mWindowAttributes.type, config.windowConfiguration.getWindowingMode(), + mWindowAttributes.softInputMode, mWindowAttributes.flags).toRect()); } return mLastWindowInsets; } @@ -3462,21 +3465,21 @@ public final class ViewRootImpl implements ViewParent, mReportNextDraw = false; mSyncBufferCallback = null; mSyncBuffer = false; - if (mLastSyncId != -1) { - mSurfaceSyncer.markSyncReady(mLastSyncId); - mLastSyncId = -1; + if (isInLocalSync()) { + mSurfaceSyncer.markSyncReady(mSyncId); + mSyncId = UNSET_SYNC_ID; } } } private void createSyncIfNeeded() { // Started a sync already or there's nothing needing to sync - if (mLastSyncId != -1 || !mReportNextDraw) { + if (isInLocalSync() || !mReportNextDraw) { return; } final int seqId = mSyncSeqId; - mLastSyncId = mSurfaceSyncer.setupSync(transaction -> { + mSyncId = mSurfaceSyncer.setupSync(transaction -> { // Callback will be invoked on executor thread so post to main thread. mHandler.postAtFrontOfQueue(() -> { mSurfaceChangedTransaction.merge(transaction); @@ -3484,9 +3487,9 @@ public final class ViewRootImpl implements ViewParent, }); }); if (DEBUG_BLAST) { - Log.d(mTag, "Setup new sync id=" + mLastSyncId); + Log.d(mTag, "Setup new sync id=" + mSyncId); } - mSurfaceSyncer.addToSync(mLastSyncId, mSyncTarget); + mSurfaceSyncer.addToSync(mSyncId, mSyncTarget); } private void notifyContentCatpureEvents() { @@ -4122,17 +4125,19 @@ public final class ViewRootImpl implements ViewParent, return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled(); } - boolean addToSync(SurfaceSyncer.SyncTarget syncable) { - if (mLastSyncId == -1) { - return false; + void addToSync(SurfaceSyncer.SyncTarget syncable) { + if (!isInLocalSync()) { + return; } - mSurfaceSyncer.addToSync(mLastSyncId, syncable); - return true; + mSurfaceSyncer.addToSync(mSyncId, syncable); } - - public boolean isInSync() { - return mLastSyncId != -1; + /** + * This VRI is currently in the middle of a sync request, but specifically one initiated from + * within VRI. + */ + public boolean isInLocalSync() { + return mSyncId != UNSET_SYNC_ID; } private void addFrameCommitCallbackIfNeeded() { @@ -10249,13 +10254,14 @@ public final class ViewRootImpl implements ViewParent, public void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId, Region interactiveRegion, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, - int interrogatingPid, long interrogatingTid, MagnificationSpec spec, Bundle args) { + int interrogatingPid, long interrogatingTid, MagnificationSpec spec, float[] matrix, + Bundle args) { ViewRootImpl viewRootImpl = mViewRootImpl.get(); if (viewRootImpl != null && viewRootImpl.mView != null) { viewRootImpl.getAccessibilityInteractionController() .findAccessibilityNodeInfoByAccessibilityIdClientThread(accessibilityNodeId, interactiveRegion, interactionId, callback, flags, interrogatingPid, - interrogatingTid, spec, args); + interrogatingTid, spec, matrix, args); } else { // We cannot make the call and notify the caller so it does not wait. try { @@ -10290,13 +10296,14 @@ public final class ViewRootImpl implements ViewParent, public void findAccessibilityNodeInfosByViewId(long accessibilityNodeId, String viewId, Region interactiveRegion, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, - int interrogatingPid, long interrogatingTid, MagnificationSpec spec) { + int interrogatingPid, long interrogatingTid, MagnificationSpec spec, + float[] matrix) { ViewRootImpl viewRootImpl = mViewRootImpl.get(); if (viewRootImpl != null && viewRootImpl.mView != null) { viewRootImpl.getAccessibilityInteractionController() .findAccessibilityNodeInfosByViewIdClientThread(accessibilityNodeId, viewId, interactiveRegion, interactionId, callback, flags, - interrogatingPid, interrogatingTid, spec); + interrogatingPid, interrogatingTid, spec, matrix); } else { // We cannot make the call and notify the caller so it does not wait. try { @@ -10311,13 +10318,14 @@ public final class ViewRootImpl implements ViewParent, public void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text, Region interactiveRegion, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, - int interrogatingPid, long interrogatingTid, MagnificationSpec spec) { + int interrogatingPid, long interrogatingTid, MagnificationSpec spec, + float[] matrix) { ViewRootImpl viewRootImpl = mViewRootImpl.get(); if (viewRootImpl != null && viewRootImpl.mView != null) { viewRootImpl.getAccessibilityInteractionController() .findAccessibilityNodeInfosByTextClientThread(accessibilityNodeId, text, interactiveRegion, interactionId, callback, flags, interrogatingPid, - interrogatingTid, spec); + interrogatingTid, spec, matrix); } else { // We cannot make the call and notify the caller so it does not wait. try { @@ -10331,13 +10339,14 @@ public final class ViewRootImpl implements ViewParent, @Override public void findFocus(long accessibilityNodeId, int focusType, Region interactiveRegion, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, - int interrogatingPid, long interrogatingTid, MagnificationSpec spec) { + int interrogatingPid, long interrogatingTid, MagnificationSpec spec, + float[] matrix) { ViewRootImpl viewRootImpl = mViewRootImpl.get(); if (viewRootImpl != null && viewRootImpl.mView != null) { viewRootImpl.getAccessibilityInteractionController() .findFocusClientThread(accessibilityNodeId, focusType, interactiveRegion, interactionId, callback, flags, interrogatingPid, interrogatingTid, - spec); + spec, matrix); } else { // We cannot make the call and notify the caller so it does not wait. try { @@ -10351,13 +10360,14 @@ public final class ViewRootImpl implements ViewParent, @Override public void focusSearch(long accessibilityNodeId, int direction, Region interactiveRegion, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, - int interrogatingPid, long interrogatingTid, MagnificationSpec spec) { + int interrogatingPid, long interrogatingTid, MagnificationSpec spec, + float[] matrix) { ViewRootImpl viewRootImpl = mViewRootImpl.get(); if (viewRootImpl != null && viewRootImpl.mView != null) { viewRootImpl.getAccessibilityInteractionController() .focusSearchClientThread(accessibilityNodeId, direction, interactiveRegion, interactionId, callback, flags, interrogatingPid, interrogatingTid, - spec); + spec, matrix); } else { // We cannot make the call and notify the caller so it does not wait. try { @@ -10889,6 +10899,10 @@ public final class ViewRootImpl implements ViewParent, private void readyToSync(SurfaceSyncer.SyncBufferCallback syncBufferCallback) { mNumSyncsInProgress++; + if (!isInLocalSync()) { + // Always sync the buffer if the sync request did not come from VRI. + mSyncBuffer = true; + } if (mAttachInfo.mThreadedRenderer != null) { HardwareRenderer.setRtAnimationsEnabled(false); } diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 555fd434e4d9..02027e4a3969 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -67,9 +67,7 @@ import java.util.List; * window manager. It provides standard UI policies such as a background, title * area, default key processing, etc. * - * <p>The only existing implementation of this abstract class is - * android.view.PhoneWindow, which you should instantiate when needing a - * Window. + * <p>The framework will instantiate an implementation of this class on behalf of the application. */ public abstract class Window { /** Flag for the "options panel" feature. This is enabled by default. */ diff --git a/core/java/android/view/WindowInfo.java b/core/java/android/view/WindowInfo.java index 1edbbba09eef..a5b8720c7dec 100644 --- a/core/java/android/view/WindowInfo.java +++ b/core/java/android/view/WindowInfo.java @@ -17,6 +17,7 @@ package android.view; import android.app.ActivityTaskManager; +import android.graphics.Matrix; import android.graphics.Region; import android.os.IBinder; import android.os.Parcel; @@ -53,6 +54,11 @@ public class WindowInfo implements Parcelable { public boolean hasFlagWatchOutsideTouch; public int displayId = Display.INVALID_DISPLAY; public int taskId = ActivityTaskManager.INVALID_TASK_ID; + // The matrix applied to the bounds in window coordinate to get the corresponding values in + // screen coordinates. + public float[] mTransformMatrix = new float[9]; + + public MagnificationSpec mMagnificationSpec = new MagnificationSpec(); private WindowInfo() { /* do nothing - hide constructor */ @@ -81,6 +87,9 @@ public class WindowInfo implements Parcelable { window.accessibilityIdOfAnchor = other.accessibilityIdOfAnchor; window.inPictureInPicture = other.inPictureInPicture; window.hasFlagWatchOutsideTouch = other.hasFlagWatchOutsideTouch; + for (int i = 0; i < window.mTransformMatrix.length; i++) { + window.mTransformMatrix[i] = other.mTransformMatrix[i]; + } if (other.childTokens != null && !other.childTokens.isEmpty()) { if (window.childTokens == null) { @@ -89,7 +98,7 @@ public class WindowInfo implements Parcelable { window.childTokens.addAll(other.childTokens); } } - + window.mMagnificationSpec.setTo(other.mMagnificationSpec); return window; } @@ -118,6 +127,7 @@ public class WindowInfo implements Parcelable { parcel.writeLong(accessibilityIdOfAnchor); parcel.writeInt(inPictureInPicture ? 1 : 0); parcel.writeInt(hasFlagWatchOutsideTouch ? 1 : 0); + parcel.writeFloatArray(mTransformMatrix); if (childTokens != null && !childTokens.isEmpty()) { parcel.writeInt(1); @@ -125,6 +135,7 @@ public class WindowInfo implements Parcelable { } else { parcel.writeInt(0); } + mMagnificationSpec.writeToParcel(parcel, flags); } @Override @@ -145,6 +156,10 @@ public class WindowInfo implements Parcelable { builder.append(", accessibility anchor=").append(accessibilityIdOfAnchor); builder.append(", pictureInPicture=").append(inPictureInPicture); builder.append(", watchOutsideTouch=").append(hasFlagWatchOutsideTouch); + Matrix matrix = new Matrix(); + matrix.setValues(mTransformMatrix); + builder.append(", mTransformMatrix=").append(matrix); + builder.append(", mMagnificationSpec=").append(mMagnificationSpec); builder.append(']'); return builder.toString(); } @@ -163,7 +178,7 @@ public class WindowInfo implements Parcelable { accessibilityIdOfAnchor = parcel.readLong(); inPictureInPicture = (parcel.readInt() == 1); hasFlagWatchOutsideTouch = (parcel.readInt() == 1); - + parcel.readFloatArray(mTransformMatrix); final boolean hasChildren = (parcel.readInt() == 1); if (hasChildren) { if (childTokens == null) { @@ -171,6 +186,7 @@ public class WindowInfo implements Parcelable { } parcel.readBinderList(childTokens); } + mMagnificationSpec = MagnificationSpec.CREATOR.createFromParcel(parcel); } private void clear() { @@ -188,6 +204,10 @@ public class WindowInfo implements Parcelable { } inPictureInPicture = false; hasFlagWatchOutsideTouch = false; + for (int i = 0; i < mTransformMatrix.length; i++) { + mTransformMatrix[i] = 0; + } + mMagnificationSpec.clear(); } public static final @android.annotation.NonNull Parcelable.Creator<WindowInfo> CREATOR = diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java index ba3417980a3d..c846175699f2 100644 --- a/core/java/android/view/WindowInsets.java +++ b/core/java/android/view/WindowInsets.java @@ -32,8 +32,6 @@ import static android.view.WindowInsets.Type.all; import static android.view.WindowInsets.Type.ime; import static android.view.WindowInsets.Type.indexOf; import static android.view.WindowInsets.Type.systemBars; -import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; -import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; import android.annotation.IntDef; import android.annotation.IntRange; @@ -46,7 +44,6 @@ import android.graphics.Rect; import android.util.SparseArray; import android.view.View.OnApplyWindowInsetsListener; import android.view.WindowInsets.Type.InsetsType; -import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethod; @@ -675,7 +672,7 @@ public final class WindowInsets { @Deprecated @NonNull public Insets getStableInsets() { - return getInsets(mTypeMaxInsetsMap, mCompatInsetsTypes); + return getInsets(mTypeMaxInsetsMap, systemBars()); } /** @@ -1600,17 +1597,6 @@ public final class WindowInsets { public static @InsetsType int all() { return 0xFFFFFFFF; } - - /** - * Checks whether the specified type is considered to be part of visible insets. - * @hide - */ - public static boolean isVisibleInsetsType(int type, - @SoftInputModeFlags int softInputModeFlags) { - int softInputMode = softInputModeFlags & SOFT_INPUT_MASK_ADJUST; - return (type & Type.systemBars()) != 0 - || (softInputMode != SOFT_INPUT_ADJUST_NOTHING && (type & Type.ime()) != 0); - } } /** diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 8e9f9d9fb4f3..cfe44bbbf3c6 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -3590,12 +3590,13 @@ public interface WindowManager extends ViewManager { /** * If specified, the insets provided by this window will be our window frame minus the - * insets specified by providedInternalInsets. This should not be used together with - * {@link WindowState#mGivenContentInsets}. If both of them are set, both will be applied. + * insets specified by providedInternalInsets for each type. This should not be used + * together with {@link WindowState#mGivenContentInsets}. If both of them are set, both will + * be applied. * * @hide */ - public Insets providedInternalInsets = Insets.NONE; + public Insets[] providedInternalInsets; /** * If specified, the insets provided by this window for the IME will be our window frame @@ -3603,7 +3604,7 @@ public interface WindowManager extends ViewManager { * * @hide */ - public Insets providedInternalImeInsets = Insets.NONE; + public Insets[] providedInternalImeInsets; /** * If specified, the frame that used to calculate relative {@link RoundedCorner} will be @@ -3989,8 +3990,18 @@ public interface WindowManager extends ViewManager { } else { out.writeInt(0); } - providedInternalInsets.writeToParcel(out, 0 /* parcelableFlags */); - providedInternalImeInsets.writeToParcel(out, 0 /* parcelableFlags */); + if (providedInternalInsets != null) { + out.writeInt(providedInternalInsets.length); + out.writeTypedArray(providedInternalInsets, 0 /* parcelableFlags */); + } else { + out.writeInt(0); + } + if (providedInternalImeInsets != null) { + out.writeInt(providedInternalImeInsets.length); + out.writeTypedArray(providedInternalImeInsets, 0 /* parcelableFlags */); + } else { + out.writeInt(0); + } out.writeBoolean(insetsRoundedCornerFrame); if (paramsForRotation != null) { checkNonRecursiveParams(); @@ -4070,8 +4081,16 @@ public interface WindowManager extends ViewManager { providesInsetsTypes = new int[insetsTypesLength]; in.readIntArray(providesInsetsTypes); } - providedInternalInsets = Insets.CREATOR.createFromParcel(in); - providedInternalImeInsets = Insets.CREATOR.createFromParcel(in); + int providedInternalInsetsLength = in.readInt(); + if (providedInternalInsetsLength > 0) { + providedInternalInsets = new Insets[providedInternalInsetsLength]; + in.readTypedArray(providedInternalInsets, Insets.CREATOR); + } + int providedInternalImeInsetsLength = in.readInt(); + if (providedInternalImeInsetsLength > 0) { + providedInternalImeInsets = new Insets[providedInternalImeInsetsLength]; + in.readTypedArray(providedInternalImeInsets, Insets.CREATOR); + } insetsRoundedCornerFrame = in.readBoolean(); int paramsForRotationLength = in.readInt(); if (paramsForRotationLength > 0) { @@ -4374,12 +4393,12 @@ public interface WindowManager extends ViewManager { changes |= LAYOUT_CHANGED; } - if (!providedInternalInsets.equals(o.providedInternalInsets)) { + if (!Arrays.equals(providedInternalInsets, o.providedInternalInsets)) { providedInternalInsets = o.providedInternalInsets; changes |= LAYOUT_CHANGED; } - if (!providedInternalImeInsets.equals(o.providedInternalImeInsets)) { + if (!Arrays.equals(providedInternalImeInsets, o.providedInternalImeInsets)) { providedInternalImeInsets = o.providedInternalImeInsets; changes |= LAYOUT_CHANGED; } @@ -4590,13 +4609,21 @@ public interface WindowManager extends ViewManager { sb.append(InsetsState.typeToString(providesInsetsTypes[i])); } } - if (!providedInternalInsets.equals(Insets.NONE)) { + if (providedInternalInsets != null) { + sb.append(System.lineSeparator()); sb.append(" providedInternalInsets="); - sb.append(providedInternalInsets); + for (int i = 0; i < providedInternalInsets.length; ++i) { + if (i > 0) sb.append(' '); + sb.append((providedInternalInsets[i])); + } } - if (!providedInternalImeInsets.equals(Insets.NONE)) { + if (providedInternalImeInsets != null) { + sb.append(System.lineSeparator()); sb.append(" providedInternalImeInsets="); - sb.append(providedInternalImeInsets); + for (int i = 0; i < providedInternalImeInsets.length; ++i) { + if (i > 0) sb.append(' '); + sb.append((providedInternalImeInsets[i])); + } } if (insetsRoundedCornerFrame) { sb.append(" insetsRoundedCornerFrame="); diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index 0008aa64efa4..90e349864092 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -5682,6 +5682,7 @@ public class AccessibilityNodeInfo implements Parcelable { * @param heading Whether the item is a heading. (Prefer * {@link AccessibilityNodeInfo#setHeading(boolean)}) * @param selected Whether the item is selected. + * @removed */ @Deprecated @NonNull diff --git a/core/java/android/view/accessibility/IAccessibilityEmbeddedConnection.aidl b/core/java/android/view/accessibility/IAccessibilityEmbeddedConnection.aidl index 707099ef09f4..75d81ed6f667 100644 --- a/core/java/android/view/accessibility/IAccessibilityEmbeddedConnection.aidl +++ b/core/java/android/view/accessibility/IAccessibilityEmbeddedConnection.aidl @@ -28,5 +28,5 @@ interface IAccessibilityEmbeddedConnection { void disassociateEmbeddedHierarchy(); - oneway void setScreenMatrix(in float[] matrixValues); + oneway void setWindowMatrix(in float[] matrixValues); } diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl index deb0d2a3fd3d..472a36361585 100644 --- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl +++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl @@ -34,23 +34,24 @@ oneway interface IAccessibilityInteractionConnection { void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId, in Region bounds, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, long interrogatingTid, in MagnificationSpec spec, - in Bundle arguments); + in float[] matrixValues, in Bundle arguments); void findAccessibilityNodeInfosByViewId(long accessibilityNodeId, String viewId, in Region bounds, int interactionId, IAccessibilityInteractionConnectionCallback callback, - int flags, int interrogatingPid, long interrogatingTid, in MagnificationSpec spec); + int flags, int interrogatingPid, long interrogatingTid, in MagnificationSpec spec, + in float[] matrix); void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text, in Region bounds, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, - int interrogatingPid, long interrogatingTid, in MagnificationSpec spec); + int interrogatingPid, long interrogatingTid, in MagnificationSpec spec, in float[] matrixValues); void findFocus(long accessibilityNodeId, int focusType, in Region bounds, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, - long interrogatingTid, in MagnificationSpec spec); + long interrogatingTid, in MagnificationSpec spec, in float[] matrixValues); void focusSearch(long accessibilityNodeId, int direction, in Region bounds, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, - long interrogatingTid, in MagnificationSpec spec); + long interrogatingTid, in MagnificationSpec spec, in float[] matrixValues); void performAccessibilityAction(long accessibilityNodeId, int action, in Bundle arguments, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index decd9a547edb..c1ec168af145 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -56,6 +56,9 @@ import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import android.view.WindowManagerGlobal; +import android.window.OnBackInvokedCallback; +import android.window.OnBackInvokedDispatcher; +import android.window.WindowOnBackInvokedDispatcher; import com.android.internal.R; @@ -277,6 +280,8 @@ public class PopupWindow { private boolean mPopupViewInitialLayoutDirectionInherited; + private OnBackInvokedCallback mBackCallback; + /** * <p>Create a new empty, non focusable popup window of dimension (0,0).</p> * @@ -2028,6 +2033,8 @@ public class PopupWindow { final PopupDecorView decorView = mDecorView; final View contentView = mContentView; + unregisterBackCallback(decorView.findOnBackInvokedDispatcher()); + final ViewGroup contentHolder; final ViewParent contentParent = contentView.getParent(); if (contentParent instanceof ViewGroup) { @@ -2082,6 +2089,15 @@ public class PopupWindow { } } + private void unregisterBackCallback(@Nullable OnBackInvokedDispatcher onBackInvokedDispatcher) { + OnBackInvokedCallback backCallback = mBackCallback; + mBackCallback = null; + if (onBackInvokedDispatcher != null && backCallback != null) { + onBackInvokedDispatcher.unregisterOnBackInvokedCallback( + backCallback); + } + } + /** * Returns the window-relative epicenter bounds to be used by enter and * exit transitions. @@ -2725,6 +2741,30 @@ public class PopupWindow { } } } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(mContext)) { + return; + } + + OnBackInvokedDispatcher dispatcher = findOnBackInvokedDispatcher(); + if (dispatcher == null) { + return; + } + + mBackCallback = PopupWindow.this::dismiss; + + dispatcher.registerOnBackInvokedCallback(OnBackInvokedDispatcher.PRIORITY_DEFAULT, + mBackCallback); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + unregisterBackCallback(findOnBackInvokedDispatcher()); + } } private class PopupBackgroundView extends FrameLayout { diff --git a/core/java/android/window/BackEvent.java b/core/java/android/window/BackEvent.java index 14985c987f97..1024e2e50c3e 100644 --- a/core/java/android/window/BackEvent.java +++ b/core/java/android/window/BackEvent.java @@ -46,8 +46,8 @@ public class BackEvent implements Parcelable { @Retention(RetentionPolicy.SOURCE) public @interface SwipeEdge{} - private final int mTouchX; - private final int mTouchY; + private final float mTouchX; + private final float mTouchY; private final float mProgress; @SwipeEdge @@ -58,14 +58,14 @@ public class BackEvent implements Parcelable { /** * Creates a new {@link BackEvent} instance. * - * @param touchX Absolute X location of the touch point. - * @param touchY Absolute Y location of the touch point. + * @param touchX Absolute X location of the touch point of this event. + * @param touchY Absolute Y location of the touch point of this event. * @param progress Value between 0 and 1 on how far along the back gesture is. * @param swipeEdge Indicates which edge the swipe starts from. * @param departingAnimationTarget The remote animation target of the departing application * window. */ - public BackEvent(int touchX, int touchY, float progress, @SwipeEdge int swipeEdge, + public BackEvent(float touchX, float touchY, float progress, @SwipeEdge int swipeEdge, @Nullable RemoteAnimationTarget departingAnimationTarget) { mTouchX = touchX; mTouchY = touchY; @@ -75,8 +75,8 @@ public class BackEvent implements Parcelable { } private BackEvent(@NonNull Parcel in) { - mTouchX = in.readInt(); - mTouchY = in.readInt(); + mTouchX = in.readFloat(); + mTouchY = in.readFloat(); mProgress = in.readFloat(); mSwipeEdge = in.readInt(); mDepartingAnimationTarget = in.readTypedObject(RemoteAnimationTarget.CREATOR); @@ -101,8 +101,8 @@ public class BackEvent implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeInt(mTouchX); - dest.writeInt(mTouchY); + dest.writeFloat(mTouchX); + dest.writeFloat(mTouchY); dest.writeFloat(mProgress); dest.writeInt(mSwipeEdge); dest.writeTypedObject(mDepartingAnimationTarget, flags); @@ -118,14 +118,14 @@ public class BackEvent implements Parcelable { /** * Returns the absolute X location of the touch point. */ - public int getTouchX() { + public float getTouchX() { return mTouchX; } /** * Returns the absolute Y location of the touch point. */ - public int getTouchY() { + public float getTouchY() { return mTouchY; } diff --git a/core/java/android/window/SplashScreenView.java b/core/java/android/window/SplashScreenView.java index 2d1deb2a57bb..bc9f74ecec99 100644 --- a/core/java/android/window/SplashScreenView.java +++ b/core/java/android/window/SplashScreenView.java @@ -16,9 +16,6 @@ package android.window; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; -import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; -import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; -import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; import static com.android.internal.jank.InteractionJankMonitor.CUJ_SPLASHSCREEN_AVD; @@ -29,11 +26,9 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.annotation.UiThread; -import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; @@ -52,15 +47,12 @@ import android.view.SurfaceView; import android.view.View; import android.view.ViewGroup; import android.view.Window; -import android.view.WindowInsetsController; -import android.view.WindowManager; import android.widget.FrameLayout; import android.widget.ImageView; import com.android.internal.R; import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.policy.DecorView; -import com.android.internal.util.ContrastColorUtil; import java.time.Duration; import java.time.Instant; @@ -87,12 +79,6 @@ public final class SplashScreenView extends FrameLayout { private static final String TAG = SplashScreenView.class.getSimpleName(); private static final boolean DEBUG = Build.IS_DEBUGGABLE; - private static final int LIGHT_BARS_MASK = - WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS - | WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; - private static final int WINDOW_FLAG_MASK = FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS - | FLAG_TRANSLUCENT_NAVIGATION | FLAG_TRANSLUCENT_STATUS; - private boolean mNotCopyable; private boolean mIsCopied; private int mInitBackgroundColor; @@ -107,9 +93,6 @@ public final class SplashScreenView extends FrameLayout { private final Rect mTmpRect = new Rect(); private final int[] mTmpPos = new int[2]; - // The host activity when transfer view to it. - private Activity mHostActivity; - @Nullable private SurfaceControlViewHost.SurfacePackage mSurfacePackageCopy; @Nullable @@ -123,14 +106,7 @@ public final class SplashScreenView extends FrameLayout { // cache original window and status private Window mWindow; - private int mAppWindowFlags; - private int mStatusBarColor; - private int mNavigationBarColor; - private int mSystemBarsAppearance; private boolean mHasRemoved; - private boolean mNavigationContrastEnforced; - private boolean mStatusContrastEnforced; - private boolean mDecorFitsSystemWindows; /** * Internal builder to create a SplashScreenView object. @@ -570,7 +546,6 @@ public final class SplashScreenView extends FrameLayout { if (decorView != null) { decorView.removeView(this); } - restoreSystemUIColors(); mWindow = null; } mHasRemoved = true; @@ -651,56 +626,12 @@ public final class SplashScreenView extends FrameLayout { } /** - * Called when this view is attached to an activity. This also makes SystemUI colors - * transparent so the content of splash screen view can draw fully. + * Called when this view is attached to a window of an activity. * * @hide */ - public void attachHostActivityAndSetSystemUIColors(Activity activity, Window window) { - mHostActivity = activity; + public void attachHostWindow(Window window) { mWindow = window; - final WindowManager.LayoutParams attr = window.getAttributes(); - mAppWindowFlags = attr.flags; - mStatusBarColor = window.getStatusBarColor(); - mNavigationBarColor = window.getNavigationBarColor(); - mSystemBarsAppearance = window.getInsetsController().getSystemBarsAppearance(); - mNavigationContrastEnforced = window.isNavigationBarContrastEnforced(); - mStatusContrastEnforced = window.isStatusBarContrastEnforced(); - mDecorFitsSystemWindows = window.decorFitsSystemWindows(); - - applySystemBarsContrastColor(window.getInsetsController(), mInitBackgroundColor); - // Let app draw the background of bars. - window.addFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); - // Use specified bar colors instead of window background. - window.clearFlags(FLAG_TRANSLUCENT_STATUS | FLAG_TRANSLUCENT_NAVIGATION); - window.setStatusBarColor(Color.TRANSPARENT); - window.setNavigationBarColor(Color.TRANSPARENT); - window.setDecorFitsSystemWindows(false); - window.setStatusBarContrastEnforced(false); - window.setNavigationBarContrastEnforced(false); - } - - /** Called when this view is removed from the host activity. */ - private void restoreSystemUIColors() { - mWindow.setFlags(mAppWindowFlags, WINDOW_FLAG_MASK); - mWindow.setStatusBarColor(mStatusBarColor); - mWindow.setNavigationBarColor(mNavigationBarColor); - mWindow.getInsetsController().setSystemBarsAppearance(mSystemBarsAppearance, - LIGHT_BARS_MASK); - mWindow.setDecorFitsSystemWindows(mDecorFitsSystemWindows); - mWindow.setStatusBarContrastEnforced(mStatusContrastEnforced); - mWindow.setNavigationBarContrastEnforced(mNavigationContrastEnforced); - } - - /** - * Makes the icon color of system bars contrast. - * @hide - */ - public static void applySystemBarsContrastColor(WindowInsetsController windowInsetsController, - int backgroundColor) { - final int lightBarAppearance = ContrastColorUtil.isColorLight(backgroundColor) - ? LIGHT_BARS_MASK : 0; - windowInsetsController.setSystemBarsAppearance(lightBarAppearance, LIGHT_BARS_MASK); } /** diff --git a/core/java/android/window/TaskFragmentInfo.java b/core/java/android/window/TaskFragmentInfo.java index a118f9a8188f..f72164e1f53f 100644 --- a/core/java/android/window/TaskFragmentInfo.java +++ b/core/java/android/window/TaskFragmentInfo.java @@ -52,9 +52,6 @@ public final class TaskFragmentInfo implements Parcelable { @NonNull private final Configuration mConfiguration = new Configuration(); - /** Whether the TaskFragment contains any child Window Container. */ - private final boolean mIsEmpty; - /** The number of the running activities in the TaskFragment. */ private final int mRunningActivityCount; @@ -77,21 +74,27 @@ public final class TaskFragmentInfo implements Parcelable { */ private final boolean mIsTaskClearedForReuse; + /** + * Whether the last running activity in the TaskFragment was reparented to a different Task + * because it is entering PiP. + */ + private final boolean mIsTaskFragmentClearedForPip; + /** @hide */ public TaskFragmentInfo( @NonNull IBinder fragmentToken, @NonNull WindowContainerToken token, - @NonNull Configuration configuration, boolean isEmpty, int runningActivityCount, + @NonNull Configuration configuration, int runningActivityCount, boolean isVisible, @NonNull List<IBinder> activities, @NonNull Point positionInParent, - boolean isTaskClearedForReuse) { + boolean isTaskClearedForReuse, boolean isTaskFragmentClearedForPip) { mFragmentToken = requireNonNull(fragmentToken); mToken = requireNonNull(token); mConfiguration.setTo(configuration); - mIsEmpty = isEmpty; mRunningActivityCount = runningActivityCount; mIsVisible = isVisible; mActivities.addAll(activities); mPositionInParent = requireNonNull(positionInParent); mIsTaskClearedForReuse = isTaskClearedForReuse; + mIsTaskFragmentClearedForPip = isTaskFragmentClearedForPip; } @NonNull @@ -110,7 +113,7 @@ public final class TaskFragmentInfo implements Parcelable { } public boolean isEmpty() { - return mIsEmpty; + return mRunningActivityCount == 0; } public boolean hasRunningActivity() { @@ -140,6 +143,11 @@ public final class TaskFragmentInfo implements Parcelable { return mIsTaskClearedForReuse; } + /** @hide */ + public boolean isTaskFragmentClearedForPip() { + return mIsTaskFragmentClearedForPip; + } + @WindowingMode public int getWindowingMode() { return mConfiguration.windowConfiguration.getWindowingMode(); @@ -156,25 +164,25 @@ public final class TaskFragmentInfo implements Parcelable { return mFragmentToken.equals(that.mFragmentToken) && mToken.equals(that.mToken) - && mIsEmpty == that.mIsEmpty && mRunningActivityCount == that.mRunningActivityCount && mIsVisible == that.mIsVisible && getWindowingMode() == that.getWindowingMode() && mActivities.equals(that.mActivities) && mPositionInParent.equals(that.mPositionInParent) - && mIsTaskClearedForReuse == that.mIsTaskClearedForReuse; + && mIsTaskClearedForReuse == that.mIsTaskClearedForReuse + && mIsTaskFragmentClearedForPip == that.mIsTaskFragmentClearedForPip; } private TaskFragmentInfo(Parcel in) { mFragmentToken = in.readStrongBinder(); mToken = in.readTypedObject(WindowContainerToken.CREATOR); mConfiguration.readFromParcel(in); - mIsEmpty = in.readBoolean(); mRunningActivityCount = in.readInt(); mIsVisible = in.readBoolean(); in.readBinderList(mActivities); mPositionInParent = requireNonNull(in.readTypedObject(Point.CREATOR)); mIsTaskClearedForReuse = in.readBoolean(); + mIsTaskFragmentClearedForPip = in.readBoolean(); } /** @hide */ @@ -183,12 +191,12 @@ public final class TaskFragmentInfo implements Parcelable { dest.writeStrongBinder(mFragmentToken); dest.writeTypedObject(mToken, flags); mConfiguration.writeToParcel(dest, flags); - dest.writeBoolean(mIsEmpty); dest.writeInt(mRunningActivityCount); dest.writeBoolean(mIsVisible); dest.writeBinderList(mActivities); dest.writeTypedObject(mPositionInParent, flags); dest.writeBoolean(mIsTaskClearedForReuse); + dest.writeBoolean(mIsTaskFragmentClearedForPip); } @NonNull @@ -210,12 +218,12 @@ public final class TaskFragmentInfo implements Parcelable { return "TaskFragmentInfo{" + " fragmentToken=" + mFragmentToken + " token=" + mToken - + " isEmpty=" + mIsEmpty + " runningActivityCount=" + mRunningActivityCount + " isVisible=" + mIsVisible + " activities=" + mActivities + " positionInParent=" + mPositionInParent + " isTaskClearedForReuse=" + mIsTaskClearedForReuse + + " isTaskFragmentClearedForPip" + mIsTaskFragmentClearedForPip + "}"; } diff --git a/core/java/com/android/internal/app/LocalePickerWithRegion.java b/core/java/com/android/internal/app/LocalePickerWithRegion.java index 9fe4d67b26ce..314b0a0c81db 100644 --- a/core/java/com/android/internal/app/LocalePickerWithRegion.java +++ b/core/java/com/android/internal/app/LocalePickerWithRegion.java @@ -129,6 +129,12 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O boolean isForCountryMode = parent != null; if (!TextUtils.isEmpty(appPackageName) && !isForCountryMode) { + // Filter current system locale to add them into suggestion + LocaleList systemLangList = LocaleList.getDefault(); + for(int i = 0; i < systemLangList.size(); i++) { + langTagsToIgnore.add(systemLangList.get(i).toLanguageTag()); + } + if (appCurrentLocale != null) { Log.d(TAG, "appCurrentLocale: " + appCurrentLocale.getLocale().toLanguageTag()); langTagsToIgnore.add(appCurrentLocale.getLocale().toLanguageTag()); @@ -168,9 +174,21 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O result.mLocaleStatus == LocaleStatus.GET_SUPPORTED_LANGUAGE_FROM_LOCAL_CONFIG || result.mLocaleStatus == LocaleStatus.GET_SUPPORTED_LANGUAGE_FROM_ASSET; + // Add current system language into suggestion list + for(LocaleStore.LocaleInfo localeInfo: LocaleStore.getSystemCurrentLocaleInfo()) { + boolean isNotCurrentLocale = appCurrentLocale == null + || !localeInfo.getLocale().equals(appCurrentLocale.getLocale()); + if (!isForCountryMode && isNotCurrentLocale) { + mLocaleList.add(localeInfo); + } + } + + // Filter the language not support in app mLocaleList = filterTheLanguagesNotSupportedInApp( shouldShowList, result.mAppSupportedLocales); + Log.d(TAG, "mLocaleList after app-supported filter: " + mLocaleList.size()); + // Add "system language" if (!isForCountryMode && shouldShowList) { mLocaleList.add(LocaleStore.getSystemDefaultLocaleInfo(appCurrentLocale == null)); @@ -190,7 +208,6 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O } } } - Log.d(TAG, "mLocaleList after app-supported filter: " + filteredList.size()); } return filteredList; diff --git a/core/java/com/android/internal/app/LocaleStore.java b/core/java/com/android/internal/app/LocaleStore.java index eb11b9b8b138..9480362d4fe5 100644 --- a/core/java/com/android/internal/app/LocaleStore.java +++ b/core/java/com/android/internal/app/LocaleStore.java @@ -25,9 +25,11 @@ import android.telephony.TelephonyManager; import android.util.Log; import java.io.Serializable; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.IllformedLocaleException; +import java.util.List; import java.util.Locale; import java.util.Set; @@ -278,6 +280,22 @@ public class LocaleStore { } /** + * Returns a list of system languages with LocaleInfo + */ + public static List<LocaleInfo> getSystemCurrentLocaleInfo() { + List<LocaleInfo> localeList = new ArrayList<>(); + + LocaleList systemLangList = LocaleList.getDefault(); + for(int i = 0; i < systemLangList.size(); i++) { + LocaleInfo systemLocaleInfo = new LocaleInfo(systemLangList.get(i)); + systemLocaleInfo.mSuggestionFlags |= LocaleInfo.SUGGESTION_TYPE_SIM; + systemLocaleInfo.mIsTranslated = true; + localeList.add(systemLocaleInfo); + } + return localeList; + } + + /** * The "system default" is special case for per-app picker. Intentionally keep the locale * empty to let activity know "system default" been selected. */ diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index bfd8ff923dc1..17c2dc09140e 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -1480,7 +1480,7 @@ public class ResolverActivity extends Activity implements if (intent != null) { prepareIntentForCrossProfileLaunch(intent); } - safelyStartActivityInternal(otherProfileResolveInfo, + safelyStartActivityAsUser(otherProfileResolveInfo, mMultiProfilePagerAdapter.getInactiveListAdapter().mResolverListController .getUserHandle()); }); diff --git a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java index 68b8968fe399..18fde4794969 100644 --- a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java +++ b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java @@ -217,22 +217,18 @@ public class SuggestedLocaleAdapter extends BaseAdapter implements Filterable { break; case TYPE_SYSTEM_LANGUAGE_FOR_APP_LANGUAGE_PICKER: if (!(convertView instanceof ViewGroup)) { + TextView title; if (((LocaleStore.LocaleInfo)getItem(position)).isAppCurrentLocale()) { convertView = mInflater.inflate( - R.layout.app_language_picker_system_current, parent, false); + R.layout.app_language_picker_current_locale_item, parent, false); + title = convertView.findViewById(R.id.language_picker_item); } else { convertView = mInflater.inflate( - R.layout.app_language_picker_system_default, parent, false); + R.layout.language_picker_item, parent, false); + title = convertView.findViewById(R.id.locale); } + title.setText(R.string.system_locale_title); } - - Locale defaultLocale = Locale.getDefault(); - TextView title = convertView.findViewById(R.id.locale); - title.setText(R.string.system_locale_title); - title.setTextLocale(defaultLocale); - TextView subtitle = convertView.findViewById(R.id.system_locale_subtitle); - subtitle.setText(defaultLocale.getDisplayName()); - subtitle.setTextLocale(defaultLocale); break; case TYPE_CURRENT_LOCALE: if (!(convertView instanceof ViewGroup)) { diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java index f19bfc669997..c94438e3cee8 100644 --- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java +++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java @@ -536,6 +536,12 @@ public final class SystemUiDeviceConfigFlags { */ public static final String CLIPBOARD_OVERLAY_ENABLED = "clipboard_overlay_enabled"; + /** + * (boolean) Whether widget provider info would be saved to / loaded from system persistence + * layer as opposed to individual manifests in respective apps. + */ + public static final String PERSISTS_WIDGET_PROVIDER_INFO = "persists_widget_provider_info"; + private SystemUiDeviceConfigFlags() { } } diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index 2f7c0152207f..1db4bbba9ad5 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -22,7 +22,7 @@ import static android.os.Build.VERSION_CODES.M; import static android.os.Build.VERSION_CODES.N; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; -import static android.view.InsetsState.clearCompatInsets; +import static android.view.InsetsState.clearsCompatInsets; import static android.view.View.MeasureSpec.AT_MOST; import static android.view.View.MeasureSpec.EXACTLY; import static android.view.View.MeasureSpec.getMode; @@ -1120,11 +1120,11 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind : controller.getSystemBarsAppearance(); if (insets != null) { - final boolean clearCompatInsets = clearCompatInsets(attrs.type, attrs.flags, + final boolean clearsCompatInsets = clearsCompatInsets(attrs.type, attrs.flags, getResources().getConfiguration().windowConfiguration.getWindowingMode()); final Insets stableBarInsets = insets.getInsetsIgnoringVisibility( WindowInsets.Type.systemBars()); - final Insets systemInsets = clearCompatInsets + final Insets systemInsets = clearsCompatInsets ? Insets.NONE : Insets.min(insets.getInsets(WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout()), stableBarInsets); diff --git a/core/java/com/android/internal/policy/ForceShowNavigationBarSettingsObserver.java b/core/java/com/android/internal/policy/KidsModeSettingsObserver.java index 75dce5a278ff..8a1d407382bc 100644 --- a/core/java/com/android/internal/policy/ForceShowNavigationBarSettingsObserver.java +++ b/core/java/com/android/internal/policy/KidsModeSettingsObserver.java @@ -24,17 +24,17 @@ import android.os.UserHandle; import android.provider.Settings; /** - * A ContentObserver for listening force show navigation bar relative setting keys: + * A ContentObserver for listening kids mode relative setting keys: * - {@link Settings.Secure#NAVIGATION_MODE} - * - {@link Settings.Secure#NAV_BAR_FORCE_VISIBLE} + * - {@link Settings.Secure#NAV_BAR_KIDS_MODE} * * @hide */ -public class ForceShowNavigationBarSettingsObserver extends ContentObserver { +public class KidsModeSettingsObserver extends ContentObserver { private Context mContext; private Runnable mOnChangeRunnable; - public ForceShowNavigationBarSettingsObserver(Handler handler, Context context) { + public KidsModeSettingsObserver(Handler handler, Context context) { super(handler); mContext = context; } @@ -52,7 +52,7 @@ public class ForceShowNavigationBarSettingsObserver extends ContentObserver { Settings.Secure.getUriFor(Settings.Secure.NAVIGATION_MODE), false, this, UserHandle.USER_ALL); r.registerContentObserver( - Settings.Secure.getUriFor(Settings.Secure.NAV_BAR_FORCE_VISIBLE), + Settings.Secure.getUriFor(Settings.Secure.NAV_BAR_KIDS_MODE), false, this, UserHandle.USER_ALL); } @@ -78,6 +78,6 @@ public class ForceShowNavigationBarSettingsObserver extends ContentObserver { return Settings.Secure.getIntForUser(mContext.getContentResolver(), Settings.Secure.NAVIGATION_MODE, 0, UserHandle.USER_CURRENT) == 0 && Settings.Secure.getIntForUser(mContext.getContentResolver(), - Settings.Secure.NAV_BAR_FORCE_VISIBLE, 0, UserHandle.USER_CURRENT) == 1; + Settings.Secure.NAV_BAR_KIDS_MODE, 0, UserHandle.USER_CURRENT) == 1; } } diff --git a/core/java/com/android/internal/policy/SystemBarUtils.java b/core/java/com/android/internal/policy/SystemBarUtils.java index 6bf1333097f7..7a1ac071a625 100644 --- a/core/java/com/android/internal/policy/SystemBarUtils.java +++ b/core/java/com/android/internal/policy/SystemBarUtils.java @@ -43,7 +43,7 @@ public final class SystemBarUtils { * Gets the status bar height with a specific display cutout. */ public static int getStatusBarHeight(Resources res, DisplayCutout cutout) { - final int defaultSize = res.getDimensionPixelSize(R.dimen.status_bar_height); + final int defaultSize = res.getDimensionPixelSize(R.dimen.status_bar_height_default); final int safeInsetTop = cutout == null ? 0 : cutout.getSafeInsetTop(); final int waterfallInsetTop = cutout == null ? 0 : cutout.getWaterfallInsets().top; // The status bar height should be: @@ -73,7 +73,7 @@ public final class SystemBarUtils { } } final int defaultSize = - context.getResources().getDimensionPixelSize(R.dimen.status_bar_height); + context.getResources().getDimensionPixelSize(R.dimen.status_bar_height_default); // The status bar height should be: // Max(top cutout size, (status bar default height + waterfall top size)) return Math.max(insets.top, defaultSize + waterfallInsets.top); diff --git a/core/java/com/android/internal/security/OWNERS b/core/java/com/android/internal/security/OWNERS index 41d1d6687c42..b702df80cc7e 100644 --- a/core/java/com/android/internal/security/OWNERS +++ b/core/java/com/android/internal/security/OWNERS @@ -1,3 +1,3 @@ # Bug component: 36824 -per-file VerityUtils.java = victorhsieh@google.com +per-file VerityUtils.java = file:platform/system/security:/fsverity/OWNERS diff --git a/core/java/com/android/internal/util/LatencyTracker.java b/core/java/com/android/internal/util/LatencyTracker.java index 3f7c4d53d333..2f707a774462 100644 --- a/core/java/com/android/internal/util/LatencyTracker.java +++ b/core/java/com/android/internal/util/LatencyTracker.java @@ -48,7 +48,7 @@ import java.util.concurrent.TimeUnit; */ public class LatencyTracker { private static final String TAG = "LatencyTracker"; - private static final String SETTINGS_ENABLED_KEY = "enabled"; + public static final String SETTINGS_ENABLED_KEY = "enabled"; private static final String SETTINGS_SAMPLING_INTERVAL_KEY = "sampling_interval"; private static final boolean DEBUG = false; /** Default to being enabled on debug builds. */ diff --git a/core/jni/OWNERS b/core/jni/OWNERS index 9e5f6ea666ba..ac6b80f6d4a3 100644 --- a/core/jni/OWNERS +++ b/core/jni/OWNERS @@ -84,7 +84,7 @@ per-file LayoutlibLoader.cpp = file:/graphics/java/android/graphics/OWNERS per-file LayoutlibLoader.cpp = diegoperez@google.com, jgaillard@google.com # Verity -per-file com_android_internal_security_Verity* = ebiggers@google.com, victorhsieh@google.com +per-file com_android_internal_security_Verity* = file:platform/system/security:/fsverity/OWNERS # VINTF per-file android_os_VintfObject* = file:platform/system/libvintf:/OWNERS diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp index 973ed29d8e72..241320f31748 100644 --- a/core/jni/android_hardware_input_InputWindowHandle.cpp +++ b/core/jni/android_hardware_input_InputWindowHandle.cpp @@ -79,7 +79,6 @@ static struct { static struct { jclass clazz; jmethodID ctor; - jfieldID nativeRegion; } gRegionClassInfo; static Mutex gHandleMutex; @@ -290,10 +289,8 @@ jobject android_view_InputWindowHandle_fromWindowInfo(JNIEnv* env, gui::WindowIn region->op({r.left, r.top, r.right, r.bottom}, SkRegion::kUnion_Op); } ScopedLocalRef<jobject> regionObj(env, - env->NewObject(gRegionClassInfo.clazz, - gRegionClassInfo.ctor)); - env->SetLongField(regionObj.get(), gRegionClassInfo.nativeRegion, - reinterpret_cast<jlong>(region)); + env->NewObject(gRegionClassInfo.clazz, gRegionClassInfo.ctor, + reinterpret_cast<jlong>(region))); env->SetObjectField(inputWindowHandle, gInputWindowHandleClassInfo.touchableRegion, regionObj.get()); @@ -453,8 +450,7 @@ int register_android_view_InputWindowHandle(JNIEnv* env) { jclass regionClazz; FIND_CLASS(regionClazz, "android/graphics/Region"); gRegionClassInfo.clazz = MakeGlobalRefOrDie(env, regionClazz); - GET_METHOD_ID(gRegionClassInfo.ctor, gRegionClassInfo.clazz, "<init>", "()V"); - GET_FIELD_ID(gRegionClassInfo.nativeRegion, gRegionClassInfo.clazz, "mNativeRegion", "J"); + GET_METHOD_ID(gRegionClassInfo.ctor, gRegionClassInfo.clazz, "<init>", "(J)V"); return 0; } diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp index bce4ed78eda1..8012e0c5ac57 100644 --- a/core/jni/android_media_AudioRecord.cpp +++ b/core/jni/android_media_AudioRecord.cpp @@ -33,12 +33,13 @@ #include <nativehelper/ScopedUtfChars.h> +#include "android_media_AudioAttributes.h" #include "android_media_AudioFormat.h" #include "android_media_AudioErrors.h" #include "android_media_DeviceCallback.h" +#include "android_media_JNIUtils.h" #include "android_media_MediaMetricsJNI.h" #include "android_media_MicrophoneInfo.h" -#include "android_media_AudioAttributes.h" // ---------------------------------------------------------------------------- @@ -57,8 +58,7 @@ struct audio_record_fields_t { // these fields provide access from C++ to the... jmethodID postNativeEventInJava; //... event post callback method jfieldID nativeRecorderInJavaObj; // provides access to the C++ AudioRecord object - jfieldID nativeCallbackCookie; // provides access to the AudioRecord callback data - jfieldID nativeDeviceCallback; // provides access to the JNIDeviceCallback instance + jfieldID jniData; // provides access to AudioRecord JNI Handle }; static audio_record_fields_t javaAudioRecordFields; static struct { @@ -66,122 +66,81 @@ static struct { jfieldID fieldNanoTime; // AudioTimestamp.nanoTime } javaAudioTimestampFields; -struct audiorecord_callback_cookie { - jclass audioRecord_class; - jobject audioRecord_ref; - bool busy; - Condition cond; -}; -static Mutex sLock; -static SortedVector <audiorecord_callback_cookie *> sAudioRecordCallBackCookies; +class AudioRecordJNIStorage : public AudioRecord::IAudioRecordCallback { + private: + // Keep in sync with frameworks/base/media/java/android/media/AudioRecord.java NATIVE_EVENT_*. + enum class EventType { + EVENT_MORE_DATA = 0, // Request to read available data from buffer. + // If this event is delivered but the callback handler + // does not want to read the available data, the handler must + // explicitly ignore the event by setting frameCount to zero. + EVENT_OVERRUN = 1, // Buffer overrun occurred. + EVENT_MARKER = 2, // Record head is at the specified marker position + // (See setMarkerPosition()). + EVENT_NEW_POS = 3, // Record head is at a new position + // (See setPositionUpdatePeriod()). + EVENT_NEW_IAUDIORECORD = 4, // IAudioRecord was re-created, either due to re-routing and + // voluntary invalidation by mediaserver, or mediaserver crash. + }; -// ---------------------------------------------------------------------------- + public: + AudioRecordJNIStorage(jclass audioRecordClass, jobject audioRecordWeakRef) + : mAudioRecordClass(audioRecordClass), mAudioRecordWeakRef(audioRecordWeakRef) {} + AudioRecordJNIStorage(const AudioRecordJNIStorage &) = delete; + AudioRecordJNIStorage& operator=(const AudioRecordJNIStorage &) = delete; -#define AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT (-16) -#define AUDIORECORD_ERROR_SETUP_INVALIDCHANNELMASK (-17) -#define AUDIORECORD_ERROR_SETUP_INVALIDFORMAT (-18) -#define AUDIORECORD_ERROR_SETUP_INVALIDSOURCE (-19) -#define AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED (-20) - -// ---------------------------------------------------------------------------- -static void recorderCallback(int event, void* user, void *info) { + void onMarker(uint32_t) override { + postEvent(EventType::EVENT_MARKER); + } - audiorecord_callback_cookie *callbackInfo = (audiorecord_callback_cookie *)user; - { - Mutex::Autolock l(sLock); - if (sAudioRecordCallBackCookies.indexOf(callbackInfo) < 0) { - return; - } - callbackInfo->busy = true; - } - - switch (event) { - case AudioRecord::EVENT_MARKER: { - JNIEnv *env = AndroidRuntime::getJNIEnv(); - if (user != NULL && env != NULL) { - env->CallStaticVoidMethod( - callbackInfo->audioRecord_class, - javaAudioRecordFields.postNativeEventInJava, - callbackInfo->audioRecord_ref, event, 0,0, NULL); - if (env->ExceptionCheck()) { - env->ExceptionDescribe(); - env->ExceptionClear(); - } - } - } break; - - case AudioRecord::EVENT_NEW_POS: { - JNIEnv *env = AndroidRuntime::getJNIEnv(); - if (user != NULL && env != NULL) { - env->CallStaticVoidMethod( - callbackInfo->audioRecord_class, - javaAudioRecordFields.postNativeEventInJava, - callbackInfo->audioRecord_ref, event, 0,0, NULL); - if (env->ExceptionCheck()) { - env->ExceptionDescribe(); - env->ExceptionClear(); - } - } - } break; + void onNewPos(uint32_t) override { + postEvent(EventType::EVENT_NEW_POS); } - { - Mutex::Autolock l(sLock); - callbackInfo->busy = false; - callbackInfo->cond.broadcast(); + void setDeviceCallback(const sp<JNIDeviceCallback>& callback) { + mDeviceCallback = callback; } -} -static sp<JNIDeviceCallback> getJniDeviceCallback(JNIEnv* env, jobject thiz) -{ - Mutex::Autolock l(sLock); - JNIDeviceCallback* const cb = - (JNIDeviceCallback*)env->GetLongField(thiz, - javaAudioRecordFields.nativeDeviceCallback); - return sp<JNIDeviceCallback>(cb); -} + sp<JNIDeviceCallback> getDeviceCallback() const { return mDeviceCallback; } -static sp<JNIDeviceCallback> setJniDeviceCallback(JNIEnv* env, - jobject thiz, - const sp<JNIDeviceCallback>& cb) -{ - Mutex::Autolock l(sLock); - sp<JNIDeviceCallback> old = - (JNIDeviceCallback*)env->GetLongField(thiz, - javaAudioRecordFields.nativeDeviceCallback); - if (cb.get()) { - cb->incStrong((void*)setJniDeviceCallback); - } - if (old != 0) { - old->decStrong((void*)setJniDeviceCallback); + jobject getAudioTrackWeakRef() const & { return mAudioRecordWeakRef.get(); } + + // If we attempt to get a jobject from a rvalue, it will soon go out of + // scope, and the reference count can drop to zero, which is unsafe. + jobject getAudioTrackWeakRef() const && = delete; + + private: + void postEvent(EventType event, int arg = 0) const { + JNIEnv *env = getJNIEnvOrDie(); + env->CallStaticVoidMethod( + static_cast<jclass>(mAudioRecordClass.get()), + javaAudioRecordFields.postNativeEventInJava, + mAudioRecordWeakRef.get(), static_cast<int>(event), arg, 0, nullptr); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + env->ExceptionClear(); + } } - env->SetLongField(thiz, javaAudioRecordFields.nativeDeviceCallback, (jlong)cb.get()); - return old; -} + + // Mutation of this object is protected using Java concurrency constructs + sp<JNIDeviceCallback> mDeviceCallback; + const GlobalRef mAudioRecordClass; + const GlobalRef mAudioRecordWeakRef; +}; // ---------------------------------------------------------------------------- -static sp<AudioRecord> getAudioRecord(JNIEnv* env, jobject thiz) -{ - Mutex::Autolock l(sLock); - AudioRecord* const ar = - (AudioRecord*)env->GetLongField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj); - return sp<AudioRecord>(ar); -} -static sp<AudioRecord> setAudioRecord(JNIEnv* env, jobject thiz, const sp<AudioRecord>& ar) +#define AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT (-16) +#define AUDIORECORD_ERROR_SETUP_INVALIDCHANNELMASK (-17) +#define AUDIORECORD_ERROR_SETUP_INVALIDFORMAT (-18) +#define AUDIORECORD_ERROR_SETUP_INVALIDSOURCE (-19) +#define AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED (-20) + +// ---------------------------------------------------------------------------- +static sp<AudioRecord> getAudioRecord(JNIEnv* env, jobject thiz) { - Mutex::Autolock l(sLock); - sp<AudioRecord> old = - (AudioRecord*)env->GetLongField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj); - if (ar.get()) { - ar->incStrong((void*)setAudioRecord); - } - if (old != 0) { - old->decStrong((void*)setAudioRecord); - } - env->SetLongField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj, (jlong)ar.get()); - return old; + return getFieldSp<AudioRecord>(env, thiz, javaAudioRecordFields.nativeRecorderInJavaObj); } // ---------------------------------------------------------------------------- @@ -211,9 +170,8 @@ static jint android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject w env->ReleasePrimitiveArrayCritical(jSession, nSession, 0); nSession = NULL; - sp<AudioRecord> lpRecorder = 0; - audiorecord_callback_cookie *lpCallbackData = NULL; - + sp<AudioRecord> lpRecorder; + sp<AudioRecordJNIStorage> callbackData; jclass clazz = env->GetObjectClass(thiz); if (clazz == NULL) { ALOGE("Can't find %s when setting up callback.", kClassPathName); @@ -287,18 +245,14 @@ static jint android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject w } // create the callback information: // this data will be passed with every AudioRecord callback - lpCallbackData = new audiorecord_callback_cookie; - lpCallbackData->audioRecord_class = (jclass)env->NewGlobalRef(clazz); // we use a weak reference so the AudioRecord object can be garbage collected. - lpCallbackData->audioRecord_ref = env->NewGlobalRef(weak_this); - lpCallbackData->busy = false; + callbackData = sp<AudioRecordJNIStorage>::make(clazz, weak_this); const status_t status = lpRecorder->set(paa->source, sampleRateInHertz, format, // word length, PCM localChanMask, frameCount, - recorderCallback, // callback_t - lpCallbackData, // void* user + callbackData, // callback 0, // notificationFrames, true, // threadCanCallJava sessionId, AudioRecord::TRANSFER_DEFAULT, flags, -1, @@ -330,11 +284,8 @@ static jint android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject w // create the callback information: // this data will be passed with every AudioRecord callback - lpCallbackData = new audiorecord_callback_cookie; - lpCallbackData->audioRecord_class = (jclass)env->NewGlobalRef(clazz); - // we use a weak reference so the AudioRecord object can be garbage collected. - lpCallbackData->audioRecord_ref = env->NewGlobalRef(weak_this); - lpCallbackData->busy = false; + // This next line makes little sense + // callbackData = sp<AudioRecordJNIStorage>::make(clazz, weak_this); } nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL); @@ -352,26 +303,20 @@ static jint android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject w env->SetIntArrayRegion(jSampleRate, 0, 1, elements); } - { // scope for the lock - Mutex::Autolock l(sLock); - sAudioRecordCallBackCookies.add(lpCallbackData); - } // save our newly created C++ AudioRecord in the "nativeRecorderInJavaObj" field // of the Java object - setAudioRecord(env, thiz, lpRecorder); + setFieldSp(env, thiz, lpRecorder, javaAudioRecordFields.nativeRecorderInJavaObj); - // save our newly created callback information in the "nativeCallbackCookie" field - // of the Java object (in mNativeCallbackCookie) so we can free the memory in finalize() - env->SetLongField(thiz, javaAudioRecordFields.nativeCallbackCookie, (jlong)lpCallbackData); + // save our newly created callback information in the "jniData" field + // of the Java object (in mNativeJNIDataHandle) so we can free the memory in finalize() + setFieldSp(env, thiz, callbackData, javaAudioRecordFields.jniData); return (jint) AUDIO_JAVA_SUCCESS; // failure: native_init_failure: - env->DeleteGlobalRef(lpCallbackData->audioRecord_class); - env->DeleteGlobalRef(lpCallbackData->audioRecord_ref); - delete lpCallbackData; - env->SetLongField(thiz, javaAudioRecordFields.nativeCallbackCookie, 0); + setFieldSp(env, thiz, sp<AudioRecord>{}, javaAudioRecordFields.nativeRecorderInJavaObj); + setFieldSp(env, thiz, sp<AudioRecordJNIStorage>{}, javaAudioRecordFields.jniData); // lpRecorder goes out of scope, so reference count drops to zero return (jint) AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED; @@ -411,36 +356,9 @@ android_media_AudioRecord_stop(JNIEnv *env, jobject thiz) #define CALLBACK_COND_WAIT_TIMEOUT_MS 1000 static void android_media_AudioRecord_release(JNIEnv *env, jobject thiz) { - sp<AudioRecord> lpRecorder = setAudioRecord(env, thiz, 0); - if (lpRecorder == NULL) { - return; - } - ALOGV("About to delete lpRecorder: %p", lpRecorder.get()); - lpRecorder->stop(); - audiorecord_callback_cookie *lpCookie = (audiorecord_callback_cookie *)env->GetLongField( - thiz, javaAudioRecordFields.nativeCallbackCookie); - - // reset the native resources in the Java object so any attempt to access - // them after a call to release fails. - env->SetLongField(thiz, javaAudioRecordFields.nativeCallbackCookie, 0); - - // delete the callback information - if (lpCookie) { - Mutex::Autolock l(sLock); - ALOGV("deleting lpCookie: %p", lpCookie); - while (lpCookie->busy) { - if (lpCookie->cond.waitRelative(sLock, - milliseconds(CALLBACK_COND_WAIT_TIMEOUT_MS)) != - NO_ERROR) { - break; - } - } - sAudioRecordCallBackCookies.remove(lpCookie); - env->DeleteGlobalRef(lpCookie->audioRecord_class); - env->DeleteGlobalRef(lpCookie->audioRecord_ref); - delete lpCookie; - } + setFieldSp(env, thiz, sp<AudioRecord>{}, javaAudioRecordFields.nativeRecorderInJavaObj); + setFieldSp(env, thiz, sp<AudioRecordJNIStorage>{}, javaAudioRecordFields.jniData); } @@ -685,43 +603,40 @@ static jint android_media_AudioRecord_getRoutedDeviceId( return (jint)lpRecorder->getRoutedDeviceId(); } +// Enable and Disable Callback methods are synchronized on the Java side static void android_media_AudioRecord_enableDeviceCallback( JNIEnv *env, jobject thiz) { sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz); - if (lpRecorder == 0) { - return; - } - sp<JNIDeviceCallback> cb = getJniDeviceCallback(env, thiz); - if (cb != 0) { + if (lpRecorder == nullptr) { return; } - audiorecord_callback_cookie *cookie = - (audiorecord_callback_cookie *)env->GetLongField(thiz, - javaAudioRecordFields.nativeCallbackCookie); - if (cookie == NULL) { + const auto pJniStorage = + getFieldSp<AudioRecordJNIStorage>(env, thiz, javaAudioRecordFields.jniData); + if (pJniStorage == nullptr || pJniStorage->getDeviceCallback() != nullptr) { return; } - cb = new JNIDeviceCallback(env, thiz, cookie->audioRecord_ref, - javaAudioRecordFields.postNativeEventInJava); - status_t status = lpRecorder->addAudioDeviceCallback(cb); - if (status == NO_ERROR) { - setJniDeviceCallback(env, thiz, cb); - } + pJniStorage->setDeviceCallback( + sp<JNIDeviceCallback>::make(env, thiz, pJniStorage->getAudioTrackWeakRef(), + javaAudioRecordFields.postNativeEventInJava)); + lpRecorder->addAudioDeviceCallback(pJniStorage->getDeviceCallback()); } static void android_media_AudioRecord_disableDeviceCallback( JNIEnv *env, jobject thiz) { - sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz); - if (lpRecorder == 0) { + if (lpRecorder == nullptr) { return; } - sp<JNIDeviceCallback> cb = setJniDeviceCallback(env, thiz, 0); - if (cb != 0) { - lpRecorder->removeAudioDeviceCallback(cb); + const auto pJniStorage = + getFieldSp<AudioRecordJNIStorage>(env, thiz, javaAudioRecordFields.jniData); + + if (pJniStorage == nullptr || pJniStorage->getDeviceCallback() == nullptr) { + return; } + lpRecorder->removeAudioDeviceCallback(pJniStorage->getDeviceCallback()); + pJniStorage->setDeviceCallback(nullptr); } // ---------------------------------------------------------------------------- @@ -962,17 +877,15 @@ static const JNINativeMethod gMethods[] = { // field names found in android/media/AudioRecord.java #define JAVA_POSTEVENT_CALLBACK_NAME "postEventFromNative" -#define JAVA_NATIVERECORDERINJAVAOBJ_FIELD_NAME "mNativeRecorderInJavaObj" -#define JAVA_NATIVECALLBACKINFO_FIELD_NAME "mNativeCallbackCookie" -#define JAVA_NATIVEDEVICECALLBACK_FIELD_NAME "mNativeDeviceCallback" +#define JAVA_NATIVEAUDIORECORDERHANDLE_FIELD_NAME "mNativeAudioRecordHandle" +#define JAVA_NATIVEJNIDATAHANDLE_FIELD_NAME "mNativeJNIDataHandle" // ---------------------------------------------------------------------------- int register_android_media_AudioRecord(JNIEnv *env) { javaAudioRecordFields.postNativeEventInJava = NULL; javaAudioRecordFields.nativeRecorderInJavaObj = NULL; - javaAudioRecordFields.nativeCallbackCookie = NULL; - javaAudioRecordFields.nativeDeviceCallback = NULL; + javaAudioRecordFields.jniData = NULL; // Get the AudioRecord class @@ -983,15 +896,12 @@ int register_android_media_AudioRecord(JNIEnv *env) "(Ljava/lang/Object;IIILjava/lang/Object;)V"); // Get the variables - // mNativeRecorderInJavaObj + // mNativeAudioRecordHandle javaAudioRecordFields.nativeRecorderInJavaObj = GetFieldIDOrDie(env, - audioRecordClass, JAVA_NATIVERECORDERINJAVAOBJ_FIELD_NAME, "J"); - // mNativeCallbackCookie - javaAudioRecordFields.nativeCallbackCookie = GetFieldIDOrDie(env, - audioRecordClass, JAVA_NATIVECALLBACKINFO_FIELD_NAME, "J"); - - javaAudioRecordFields.nativeDeviceCallback = GetFieldIDOrDie(env, - audioRecordClass, JAVA_NATIVEDEVICECALLBACK_FIELD_NAME, "J"); + audioRecordClass, JAVA_NATIVEAUDIORECORDERHANDLE_FIELD_NAME, "J"); + // mNativeJNIDataHandle + javaAudioRecordFields.jniData = GetFieldIDOrDie(env, + audioRecordClass, JAVA_NATIVEJNIDATAHANDLE_FIELD_NAME, "J"); // Get the RecordTimestamp class and fields jclass audioTimestampClass = FindClassOrDie(env, "android/media/AudioTimestamp"); diff --git a/core/jni/android_media_JNIUtils.h b/core/jni/android_media_JNIUtils.h index 9da5fa37a8f3..a413d096421c 100644 --- a/core/jni/android_media_JNIUtils.h +++ b/core/jni/android_media_JNIUtils.h @@ -64,5 +64,39 @@ inline JNIEnv* getJNIEnvOrDie() { return env; } +class GlobalRef { + public: + GlobalRef(jobject object) : GlobalRef(object, AndroidRuntime::getJNIEnv()) {} + + GlobalRef(jobject object, JNIEnv* env) { + LOG_ALWAYS_FATAL_IF(env == nullptr, "Invalid JNIEnv when attempting to create a GlobalRef"); + mGlobalRef = env->NewGlobalRef(object); + LOG_ALWAYS_FATAL_IF(env->IsSameObject(object, nullptr) == JNI_TRUE, + "Creating GlobalRef from null object"); + } + + GlobalRef(const GlobalRef& other) : GlobalRef(other.mGlobalRef) {} + + GlobalRef(GlobalRef&& other) : mGlobalRef(other.mGlobalRef) { other.mGlobalRef = nullptr; } + + // Logically const + GlobalRef& operator=(const GlobalRef& other) = delete; + + GlobalRef& operator=(GlobalRef&& other) = delete; + + ~GlobalRef() { + if (mGlobalRef == nullptr) return; // No reference to decrement + getJNIEnvOrDie()->DeleteGlobalRef(mGlobalRef); + } + + // Valid as long as this wrapper is in scope. + jobject get() const { + return mGlobalRef; + } + + private: + // Logically const. Not actually const so we can move from GlobalRef + jobject mGlobalRef; +}; } // namespace android diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index a6fbf094a030..b9d5ee4b3015 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -913,7 +913,7 @@ jboolean android_os_Process_parseProcLineArray(JNIEnv* env, jobject clazz, end = i; i++; } else if ((mode&PROC_QUOTES) != 0) { - while (buffer[i] != '"' && i < endIndex) { + while (i < endIndex && buffer[i] != '"') { i++; } end = i; diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 518fc09dee5a..51a708b76801 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -24,7 +24,9 @@ #include <memory> +#include <aidl/android/hardware/graphics/common/PixelFormat.h> #include <android-base/chrono_utils.h> +#include <android/graphics/properties.h> #include <android/graphics/region.h> #include <android/gui/BnScreenCaptureListener.h> #include <android/hardware/display/IDeviceProductInfoConstants.h> @@ -1888,6 +1890,11 @@ static jobject nativeGetDisplayDecorationSupport(JNIEnv* env, jclass clazz, return nullptr; } + using aidl::android::hardware::graphics::common::PixelFormat; + if (support.value().format == PixelFormat::R_8 && !hwui_uses_vulkan()) { + return nullptr; + } + jobject jDisplayDecorationSupport = env->NewObject(gDisplayDecorationSupportInfo.clazz, gDisplayDecorationSupportInfo.ctor); if (jDisplayDecorationSupport == nullptr) { diff --git a/core/res/res/layout/log_access_user_consent_dialog_permission.xml b/core/res/res/layout/log_access_user_consent_dialog_permission.xml index bd7efbd59c33..c88bc9282708 100644 --- a/core/res/res/layout/log_access_user_consent_dialog_permission.xml +++ b/core/res/res/layout/log_access_user_consent_dialog_permission.xml @@ -37,8 +37,8 @@ android:src="@drawable/ic_doc_document" tools:layout_editor_absoluteX="148dp" tools:layout_editor_absoluteY="35dp" - android:gravity="center" /> - + android:gravity="center" + android:tint="?attr/colorAccentPrimaryVariant"/> <TextView android:id="@+id/log_access_dialog_title" @@ -46,16 +46,18 @@ android:layout_width="wrap_content" android:layout_marginBottom="32dp" android:text="@string/log_access_confirmation_title" - android:textAppearance="?attr/textAppearanceLarge" - android:textColor="@android:color/system_neutral1_900" + android:textAppearance="@style/AllowLogAccess" + android:textColor="?android:attr/textColorPrimary" android:gravity="center" /> <TextView android:id="@+id/log_access_dialog_body" android:layout_height="wrap_content" android:layout_width="wrap_content" + android:layout_marginBottom="40dp" android:text="@string/log_access_confirmation_body" android:textAppearance="@style/PrimaryAllowLogAccess" + android:textColor="?android:attr/textColorPrimary" android:gravity="center" /> <Button diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index 3a063a5a0f5e..febd14c4c058 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is nie op die oomblik beskikbaar nie."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> is nie beskikbaar nie"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Toestemming word benodig"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kamera is nie beskikbaar nie"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Gaan voort op foon"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofoon is nie beskikbaar nie"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV-instellings is nie beskikbaar nie"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Tabletinstellings is nie beskikbaar nie"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Fooninstellings is nie beskikbaar nie"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Jou <xliff:g id="DEVICE">%1$s</xliff:g> kan nie toegang hiertoe kry nie. Probeer eerder op jou Android TV-toestel."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Jou <xliff:g id="DEVICE">%1$s</xliff:g> kan nie toegang hiertoe kry nie. Probeer eerder op jou tablet."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Jou <xliff:g id="DEVICE">%1$s</xliff:g> kan nie toegang hiertoe kry nie. Probeer eerder op jou foon."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Jy kan nie nou toegang hiertoe op jou <xliff:g id="DEVICE">%1$s</xliff:g> kry nie. Probeer eerder op jou Android TV-toestel."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Jy kan nie nou toegang hiertoe op jou <xliff:g id="DEVICE">%1$s</xliff:g> kry nie. Probeer eerder op jou tablet."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Jy kan nie nou toegang hiertoe op jou <xliff:g id="DEVICE">%1$s</xliff:g> kry nie. Probeer eerder op jou foon."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Hierdie program versoek tans bykomende sekuriteit. Probeer eerder op jou Android TV-toestel."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Hierdie program versoek tans bykomende sekuriteit. Probeer eerder op jou tablet."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Hierdie program versoek tans bykomende sekuriteit. Probeer eerder op jou foon."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Hierdie program is vir \'n ouer weergawe van Android gebou en sal dalk nie behoorlik werk nie. Probeer kyk vir opdaterings, of kontak die ontwikkelaar."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Kyk vir opdatering"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Jy het nuwe boodskappe"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Tik om meer te wete te kom en te verander."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Moenie Steur Nie het verander"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Tik om te kyk wat geblokkeer word."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Gaan kennisgewinginstellings na"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"In Android 13 het programme wat jy installeer jou toestemming nodig om kennisgewings te stuur. Tik om hierdie toestemming vir bestaande programme te verander."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Herinner my later"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Maak toe"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Stelsel"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Instellings"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Kamera"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> is vertaal."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Boodskap is vertaal uit <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> in <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Agtergrondaktiwiteit"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"’n Program gebruik tans batterykrag"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"’n Program maak tans die battery pap"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"’n Program is nog aktief"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> gebruik tans batterykrag op die agtergrond. Tik om na te gaan."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> loop tans op die agtergrond. Tik om batterygebruik te bestuur."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> kan batterylewe beïnvloed. Tik om aktiewe programme na te gaan."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Gaan aktiewe programme na"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Kan nie toegang tot die foon se kamera op jou <xliff:g id="DEVICE">%1$s</xliff:g> kry nie"</string> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index ba53134f7f34..1fd1b519f960 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> አሁን አይገኝም።"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> አይገኝም"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"ፈቃድ ያስፈልጋል"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"ካሜራ አይገኝም"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"በስልክ ላይ ይቀጥሉ"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"ማይክሮፎን አይገኝም"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"የAndroid TV ቅንጅቶች አይገኙም"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"የጡባዊ ቅንብሮች አይገኝም"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"የስልክ ቅንብሮች አይገኙም"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"ይህ በእርስዎ <xliff:g id="DEVICE">%1$s</xliff:g> ላይ ሊደረስበት አይችልም። በምትኩ በAndroid TV መሣሪያዎ ላይ ይሞክሩ።"</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"ይህ በእርስዎ <xliff:g id="DEVICE">%1$s</xliff:g> ላይ ሊደረስበት አይችልም። በምትኩ በጡባዊዎ ላይ ይሞክሩ።"</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"ይህ በእርስዎ <xliff:g id="DEVICE">%1$s</xliff:g> ላይ ሊደረስበት አይችልም። በምትኩ በስልክዎ ላይ ይሞክሩ።"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"ይህ በዚህ ጊዜ በእርስዎ <xliff:g id="DEVICE">%1$s</xliff:g> ላይ ሊደረስበት አይችልም። በምትኩ በAndroid TV መሣሪያዎ ላይ ይሞክሩ።"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"ይህ በዚህ ጊዜ በእርስዎ <xliff:g id="DEVICE">%1$s</xliff:g> ላይ ሊደረስበት አይችልም። በምትኩ በጡባዊዎ ላይ ይሞክሩ።"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"ይህ በዚህ ጊዜ በእርስዎ <xliff:g id="DEVICE">%1$s</xliff:g> ላይ ሊደረስበት አይችልም። በምትኩ በስልክዎ ላይ ይሞክሩ።"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"ይህ መተግበሪያ ተጨማሪ ደህንነትን እየጠየቀ ነው። በምትኩ በAndroid TV መሣሪያዎ ላይ ይሞክሩ።"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"ይህ መተግበሪያ ተጨማሪ ደህንነትን እየጠየቀ ነው። በምትኩ በጡባዊዎ ላይ ይሞክሩ።"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"ይህ መተግበሪያ ተጨማሪ ደህንነትን እየጠየቀ ነው። በምትኩ በስልክዎ ላይ ይሞክሩ።"</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ይህ መተግበሪያ ለቆየ የAndroid ስሪት ነው የተገነባው፣ እና በአግባቡ ላይሰራ ይችላል። ዝማኔዎች ካሉ ለመመልከት ይሞክሩ፣ ወይም ደግሞ ገንቢውን ያነጋግሩ።"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ዝማኔ ካለ አረጋግጥ"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"አዲስ መልዕክቶች አለዎት"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"የበለጠ ለመረዳት እና ለመለወጥ መታ ያድርጉ።"</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"አትረብሽ ተቀይሯል"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"ምን እንደታገደ ለመፈተሽ መታ ያድርጉ።"</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"የማሳወቂያ ቅንብሮችን ይገምግሙ"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"በAndroid 13 ላይ የሚጭኗቸው መተግበሪያዎች ማሳወቂያዎችን ለመላክ የእርስዎ ፈቃድ ያስፈልጋቸዋል። ይህን ፈቃድ ለነባር መተግበሪያዎች ለመቀየር መታ ያድርጉ።"</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"በኋላ አስታውሰኝ"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"አሰናብት"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"ሥርዓት"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"ቅንብሮች"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"ካሜራ"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> ተተርጉሟል።"</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"መልዕክት ከ<xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> ወደ <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> ተተርጉሟል።"</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"የበስተጀርባ እንቅስቃሴ"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"አንድ መተግበሪያ ባትሪን እየተጠቀመ ነው"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"አንድ መተግበሪያ ባትሪውን እየጨረሰ ነው"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"አንድ መተግበሪያ አሁንም ገቢር ነው"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> በበስተጀርባ ውስጥ ባትሪን እየተጠቀመ ነው። ለመገምገም መታ ያድርጉ።"</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> በበስተጀርባ በማሄድ ላይ ነው። የባትሪ አጠቃቀምን ለማቀናበር መታ ያድርጉ።"</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> የባትሪ ዕድሜ ላይ ተጽዕኖ ሊያሳድር ይችላል። ንቁ መተግበሪያዎችን ለመገምገም መታ ያድርጉ።"</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"ንቁ መተግበሪያዎችን ይፈትሹ"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"የስልኩን ካሜራ ከእርስዎ <xliff:g id="DEVICE">%1$s</xliff:g> መድረስ አይቻልም"</string> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index 5b2343fc9ea2..59d67e9f181e 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -1937,36 +1937,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> غير متاح الآن."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"تطبيق <xliff:g id="ACTIVITY">%1$s</xliff:g> غير متاح"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"مطلوب منح الإذن"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"الكاميرا غير متاحة"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"الاستمرار على الهاتف"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"الميكروفون غير متاح"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"إعدادات Android TV غير متاحة"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"إعدادات الجهاز اللوحي غير متاحة"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"إعدادات الهاتف غير متاحة"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"لا يمكن الوصول إلى هذا التطبيق على <xliff:g id="DEVICE">%1$s</xliff:g>. بدلاً من ذلك، جرِّب استخدام Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"لا يمكن الوصول إلى هذا التطبيق على <xliff:g id="DEVICE">%1$s</xliff:g>. بدلاً من ذلك، جرِّب استخدام جهازك اللوحي."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"لا يمكن الوصول إلى هذا التطبيق على <xliff:g id="DEVICE">%1$s</xliff:g>. بدلاً من ذلك، جرِّب استخدام هاتفك."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"لا يمكن الوصول إلى هذا التطبيق على <xliff:g id="DEVICE">%1$s</xliff:g> في الوقت الحالي. بدلاً من ذلك، جرِّب استخدام Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"لا يمكن الوصول إلى هذا التطبيق على <xliff:g id="DEVICE">%1$s</xliff:g> في الوقت الحالي. بدلاً من ذلك، جرِّب استخدام جهازك اللوحي."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"لا يمكن الوصول إلى هذا التطبيق على <xliff:g id="DEVICE">%1$s</xliff:g> في الوقت الحالي. بدلاً من ذلك، جرِّب استخدام هاتفك."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"يطلب هذا التطبيق الحصول على ميزات أمان إضافية. بدلاً من ذلك، جرِّب استخدام Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"يطلب هذا التطبيق الحصول على ميزات أمان إضافية. بدلاً من ذلك، جرِّب استخدام جهازك اللوحي."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"يطلب هذا التطبيق الحصول على ميزات أمان إضافية. بدلاً من ذلك، جرِّب استخدام هاتفك."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"تمّ إنشاء هذا التطبيق لإصدار قديم من Android وقد لا يعمل بشكل صحيح. جرِّب البحث عن تحديثات أو الاتصال بمطوّر البرامج."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"البحث عن تحديث"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"لديك رسائل جديدة"</string> @@ -2071,14 +2056,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"انقر لمعرفة مزيد من المعلومات وإجراء التغيير."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"تم تغيير ميزة \"عدم الإزعاج\""</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"انقر للاطّلاع على ما تم حظره."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"مراجعة إعدادات الإشعارات"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"في نظام التشغيل Android 13، يجب أن تحصل التطبيقات التي تُثبِّتها على إذن لإرسال الإشعارات. انقر لتغيير هذا الإذن للتطبيقات الحالية."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"تذكيري لاحقًا"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"إغلاق"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"النظام"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"الإعدادات"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"كاميرا"</string> @@ -2297,9 +2278,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> (مُترجَم)."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"الرسالة مُترجَمة من <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> إلى <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"النشاط في الخلفية"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"تطبيق يستخدم طاقة البطارية"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"ثمة تطبيق لا يزال نشطًا"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"يستخدم التطبيق <xliff:g id="APP">%1$s</xliff:g> طاقة البطارية أثناء عمله في الخلفية. انقر لمراجعة نشاط التطبيق."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"قد يؤثر استخدام التطبيق <xliff:g id="APP">%1$s</xliff:g> على عمر البطارية. انقر للاطّلاع على التطبيقات النشطة."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"التحقّق من التطبيقات النشطة"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"يتعذّر الوصول إلى كاميرا الهاتف من على جهاز <xliff:g id="DEVICE">%1$s</xliff:g>."</string> diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml index fc9601e905e2..80b2c32eb978 100644 --- a/core/res/res/values-as/strings.xml +++ b/core/res/res/values-as/strings.xml @@ -439,7 +439,7 @@ <string name="permdesc_writeCalendar" product="default" msgid="5416380074475634233">"এই এপে আপোনাৰ ফ\'নৰ কেলেণ্ডাৰত কার্যক্ৰম যোগ দিব, আঁতৰাব বা সলনি কৰিব পাৰে। ই এনে বাৰ্তা পঠিয়াব পাৰে যিবোৰ কেলেণ্ডাৰৰ গৰাকীৰ পৰা অহা যেন লাগে বা ই গৰাকীক নজনোৱাকৈ কাৰ্যক্ৰম সলনি কৰিব পাৰে৷"</string> <string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"অতিৰিক্ত অৱস্থান দেখুওৱা নির্দেশত প্ৰৱেশ কৰক"</string> <string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"অৱস্থানৰ অতিৰিক্ত নির্দেশনাসমূহত প্ৰৱেশ কৰিবলৈ এপক অনুমতি দিয়ে। ইয়ে এপটোক জিপিএছ বা অন্য অৱস্থান উৎসসমূহৰ কাৰ্যকলাপত হস্তক্ষেপ কৰাৰ সুযোগ দিব পাৰে।"</string> - <string name="permlab_accessFineLocation" msgid="6426318438195622966">"কেৱল অগ্ৰভূমিত অৱস্থানৰ সঠিক তথ্য় পাওক"</string> + <string name="permlab_accessFineLocation" msgid="6426318438195622966">"কেৱল অগ্ৰভূমিত অৱস্থানৰ সঠিক তথ্য পাওক"</string> <string name="permdesc_accessFineLocation" msgid="6732174080240016335">"এই এপ্টো ব্যৱহাৰ হৈ থকা অৱস্থাত ই অৱস্থান সেৱাসমূহৰ পৰা আপোনাৰ সঠিক অৱস্থান লাভ কৰিব পাৰে। এপ্টোৱে অৱস্থান লাভ কৰিবলৈ হ’লে আপোনাৰ ডিভাইচৰ অৱস্থান সেৱাসমূহ অন কৰি ৰাখিবই লাগিব। ইয়াৰ ফলত বেটাৰীৰ ব্যৱহাৰ বাঢ়িব পাৰে।"</string> <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"কেৱল অগ্ৰভূমিত আনুমানিক অৱস্থান এক্সেছ কৰক"</string> <string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"এই এপ্টো ব্যৱহাৰ হৈ থকা অৱস্থাত ই অৱস্থান সেৱাসমূহৰ পৰা আপোনাৰ আনুমানিক অৱস্থান লাভ কৰিব পাৰে। এপ্টোৱে অৱস্থান লাভ কৰিবলৈ হ’লে আপোনাৰ ডিভাইচৰ অৱস্থান সেৱাসমূহ অন কৰি ৰাখিবই লাগিব।"</string> @@ -471,7 +471,7 @@ <string name="permlab_accessImsCallService" msgid="442192920714863782">"আইএমএছ কল সেৱা ব্যৱহাৰ কৰিব পাৰে"</string> <string name="permdesc_accessImsCallService" msgid="6328551241649687162">"আপোনাৰ হস্তক্ষেপৰ অবিহনে আইএমএছ সেৱা ব্যৱহাৰ কৰি কল কৰিবলৈ এপক অনুমতি দিয়ে।"</string> <string name="permlab_readPhoneState" msgid="8138526903259297969">"ফ\'নৰ স্থিতি আৰু পৰিচয় পঢ়ক"</string> - <string name="permdesc_readPhoneState" msgid="7229063553502788058">"ডিভাইচত থকা ফ\'নৰ সুবিধাসমূহ ব্য়ৱহাৰ কৰিবলৈ এপটোক অনুমতি দিয়ে৷ এই অনুমতিয়ে কোনো কল সক্ৰিয় হৈ থাককেই বা নাথাকক আৰু দূৰবৰ্তী নম্বৰটো কলৰ দ্বাৰা সংযোজিত হওকেই বা নহওক এপটোক ফ\'ন নম্বৰ আৰু ডিভাইচৰ পৰিচয় নিৰ্ধাৰণ কৰিবলৈ অনুমতি দিয়ে৷"</string> + <string name="permdesc_readPhoneState" msgid="7229063553502788058">"ডিভাইচত থকা ফ\'নৰ সুবিধাসমূহ ব্যৱহাৰ কৰিবলৈ এপটোক অনুমতি দিয়ে৷ এই অনুমতিয়ে কোনো কল সক্ৰিয় হৈ থাককেই বা নাথাকক আৰু দূৰবৰ্তী নম্বৰটো কলৰ দ্বাৰা সংযোজিত হওকেই বা নহওক এপটোক ফ\'ন নম্বৰ আৰু ডিভাইচৰ পৰিচয় নিৰ্ধাৰণ কৰিবলৈ অনুমতি দিয়ে৷"</string> <string name="permlab_readBasicPhoneState" msgid="3214853233263871347">"প্ৰাথমিক টেলিফ\'নী স্থিতি আৰু পৰিচয় পঢ়ক"</string> <string name="permdesc_readBasicPhoneState" msgid="828185691675460520">"এপ্টোক ডিভাইচটোৰ প্ৰাথমিক টেলিফ’নী সুবিধাসমূহ এক্সেছ কৰাৰ অনুমতি দিয়ে।"</string> <string name="permlab_manageOwnCalls" msgid="9033349060307561370">"ছিষ্টেমৰ জৰিয়তে কল কৰিব পাৰে"</string> @@ -525,20 +525,20 @@ <string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"কেৱল আপোনাৰ Android TV ডিভাইচটোৱেই নহয়, মাল্টিকাষ্ট ঠিকনাবোৰ ব্যৱহাৰ কৰি এটা ৱাই-ফাই নেটৱর্কত থকা আটাইবোৰ ডিভাইচলৈ পঠিওৱা পেকেট লাভ কৰিবলৈ এপ্টোক অনুমতি দিয়ে। এই কার্যই নন-মাল্টিকাষ্ট ম’ডতকৈ অধিক পাৱাৰ ব্যৱহাৰ কৰে।"</string> <string name="permdesc_changeWifiMulticastState" product="default" msgid="8296627590220222740">"আপোনাৰ ফ\'নৰ লগতে ৱাই-ফাই নেটৱর্কত থকা আটাইবোৰ ডিভাইচলৈ মাল্টিকাষ্ট ঠিকনা ব্যৱহাৰ কৰি পঠিওৱা পেকেট লাভ কৰিবলৈ এপক অনুমতি দিয়ে। এই কার্যই নন-মাল্টিকাষ্ট ম\'ডতকৈ বেটাৰীৰ অধিক চাৰ্জ ব্যৱহাৰ কৰে।"</string> <string name="permlab_bluetoothAdmin" msgid="6490373569441946064">"ব্লুটুথ ছেটিং এক্সেছ কৰক"</string> - <string name="permdesc_bluetoothAdmin" product="tablet" msgid="5370837055438574863">"স্থানীয় ব্লুটুথ টে\'বলেট কনফিগাৰ কৰিবলৈ আৰু দূৰৱৰ্তী ডিভাইচসমূহৰ সৈতে যোৰা লগাবলৈ আৰু বিচাৰি উলিয়াবলৈ এপটোক অনুমতি দিয়ে।"</string> + <string name="permdesc_bluetoothAdmin" product="tablet" msgid="5370837055438574863">"স্থানীয় ব্লুটুথ টেবলেট কনফিগাৰ কৰিবলৈ আৰু দূৰৱৰ্তী ডিভাইচসমূহৰ সৈতে পেয়াৰ কৰিবলৈ আৰু বিচাৰি উলিয়াবলৈ এপ্টোক অনুমতি দিয়ে।"</string> <string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"এপ্টোক আপোনাৰ Android TV ডিভাইচটোত ব্লুটুথ কনফিগাৰ কৰিবলৈ আৰু ৰিম’ট ডিভাইচসমূহ বিচাৰি উলিয়াবলৈ আৰু পেয়াৰ কৰিবলৈ অনুমতি দিয়ে।"</string> - <string name="permdesc_bluetoothAdmin" product="default" msgid="7381341743021234863">"স্থানীয় ব্লুটুথ ফ\'ন কনফিগাৰ কৰিবলৈ আৰু দূৰৱৰ্তী ডিভাইচসমূহৰ সৈতে যোৰা লগাবলৈ আৰু বিচাৰি উলিয়াবলৈ এপটোক অনুমতি দিয়ে।"</string> + <string name="permdesc_bluetoothAdmin" product="default" msgid="7381341743021234863">"স্থানীয় ব্লুটুথ ফ’ন কনফিগাৰ কৰিবলৈ আৰু দূৰৱৰ্তী ডিভাইচসমূহৰ সৈতে পেয়াৰ কৰিবলৈ আৰু বিচাৰি উলিয়াবলৈ এপ্টোক অনুমতি দিয়ে।"</string> <string name="permlab_accessWimaxState" msgid="7029563339012437434">"WiMAXৰ লগত সংযোগ কৰক আৰু ইয়াৰ পৰা সংযোগ বিচ্ছিন্ন কৰক"</string> <string name="permdesc_accessWimaxState" msgid="5372734776802067708">"WiMAX সক্ষম হৈ আছেনে নাই আৰু সংযোজিত যিকোনো WiMAX নেটৱৰ্কৰ বিষয়ে তথ্য নিৰ্ধাৰণ কৰিবলৈ এপটোক অনুমতি দিয়ে৷"</string> <string name="permlab_changeWimaxState" msgid="6223305780806267462">"WiMAXৰ স্থিতি সলনি কৰক"</string> <string name="permdesc_changeWimaxState" product="tablet" msgid="4011097664859480108">"এপটোক টেবলেটলৈ সংযোগ কৰিবলৈ আৰু WiMAX নেটৱৰ্কসমূহৰ পৰা টেবলেটৰ সংযোগ বিচ্ছিন্ন কৰিবলৈ অনুমতি দিয়ে৷"</string> <string name="permdesc_changeWimaxState" product="tv" msgid="5373274458799425276">"এপ্টোক আপোনাৰ Android TV ডিভাইচৰ সৈতে সংযোগ কৰিবলৈ আৰু WiMAX নেটৱৰ্কসমূহৰ পৰা আপোনাৰ Android TV ডিভাইচৰ সংযোগ বিচ্ছিন্ন কৰিবলৈ অনুমতি দিয়ে।"</string> <string name="permdesc_changeWimaxState" product="default" msgid="1551666203780202101">"এপটোক ফ\'নলৈ সংযোগ কৰিবলৈ আৰু WiMAX নেটৱৰ্কসমূহৰ পৰা ফ\'নৰ সংযোগ বিচ্ছিন্ন কৰিবলৈ অনুমতি দিয়ে৷"</string> - <string name="permlab_bluetooth" msgid="586333280736937209">"ব্লুটুথ ডিভাইচবোৰৰ সৈতে যোৰা লগাওক"</string> + <string name="permlab_bluetooth" msgid="586333280736937209">"ব্লুটুথ ডিভাইচবোৰৰ সৈতে পেয়াৰ কৰক"</string> <string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"টেবলেটত ব্লুটুথৰ কনফিগাৰেশ্বন চাবলৈ আৰু যোৰা লগোৱা ডিভাইচসমূহৰ জৰিয়তে সংযোগ কৰিবলৈ আৰু সংযোগৰ অনুৰোধ স্বীকাৰ কৰিবলৈ এপটোক অনুমতি দিয়ে৷"</string> <string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"এপ্টোক আপোনাৰ Android TV ডিভাইচটোত ব্লুটুথৰ কনফিগাৰেশ্বন চাবলৈ আৰু পেয়াৰ কৰি থোৱা ডিভাইচসমূহৰ সৈতে সংযোগ কৰিবলৈ আৰু গ্ৰহণ কৰিবলৈ অনুমতি দিয়ে।"</string> <string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"ফ\'নটোত ব্লুটুথৰ কনফিগাৰেশ্বন চাবলৈ আৰু যোৰা লগোৱা ডিভাইচসমূহৰ জৰিয়তে সংযোগ কৰিবলৈ আৰু সংযোগৰ অনুৰোধ স্বীকাৰ কৰিবলৈ এপটোক অনুমতি দিয়ে৷"</string> - <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"নিকটৱৰ্তী ব্লুটুথ ডিভাইচ বিচাৰক আৰু তাৰ সৈতে সংযোগ কৰক"</string> + <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"নিকটৱৰ্তী ব্লুটুথ ডিভাইচ বিচাৰক আৰু তাৰ সৈতে পেয়াৰ কৰক"</string> <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"এপ্টোক নিকটৱৰ্তী ব্লুটুথ ডিভাইচ বিচাৰি উলিয়াবলৈ আৰু সেইসমূহৰ সৈতে পেয়াৰ কৰিবলৈ অনুমতি দিয়ে"</string> <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"পেয়াৰ কৰা ব্লুটুথ ডিভাইচৰ সৈতে সংযোগ কৰক"</string> <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"এপ্টোক পেয়াৰ কৰা ব্লুটুথ ডিভাইচৰ সৈতে সংযোগ কৰিবলৈ অনুমতি দিয়ে"</string> @@ -558,12 +558,12 @@ <string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"এপ্টোক স্ক্ৰীন লকৰ জটিলতাৰ স্তৰ (উচ্চ, মধ্যম, নিম্ন বা একেবাৰে নাই)ৰ বিষয়ে জানিবলৈ অনুমতি দিয়ে, যিয়ে স্ক্ৰীন লকৰ সম্ভাব্য দৈৰ্ঘ্য বা স্ক্ৰীন লকৰ প্ৰকাৰ দৰ্শায়। লগতে এপ্টোৱে ব্যৱহাৰকাৰীক স্ক্ৰীন লকটো এটা নিৰ্দিষ্ট স্তৰলৈ আপডে’ট কৰিবলৈ পৰামৰ্শ দিব পাৰে যিটো ব্যৱহাৰকাৰীয়ে অৱজ্ঞা কৰি পৰৱর্তী পৃষ্ঠালৈ যাব পাৰে। মনত ৰাখিব যে স্ক্ৰীন লকটো সাধাৰণ পাঠ হিচাপে ষ্ট\'ৰ কৰা নহয়; সেয়েহে, এপ্টোৱে সঠিক পাছৱৰ্ডটো জানিব নোৱাৰে।"</string> <string name="permlab_postNotification" msgid="4875401198597803658">"জাননী দেখুৱাওক"</string> <string name="permdesc_postNotification" msgid="5974977162462877075">"এপ্টোক জাননী দেখুৱাবলৈ দিয়ে"</string> - <string name="permlab_useBiometric" msgid="6314741124749633786">"বায়োমেট্ৰিক হাৰ্ডৱেৰ ব্য়ৱহাৰ কৰক"</string> - <string name="permdesc_useBiometric" msgid="7502858732677143410">"বিশ্বাসযোগ্য়তা প্ৰমাণীকৰণৰ বাবে এপক বায়োমেট্ৰিক হাৰ্ডৱেৰ ব্য়ৱহাৰ কৰিবলৈ অনুমতি দিয়ে"</string> + <string name="permlab_useBiometric" msgid="6314741124749633786">"বায়োমেট্ৰিক হাৰ্ডৱেৰ ব্যৱহাৰ কৰক"</string> + <string name="permdesc_useBiometric" msgid="7502858732677143410">"বিশ্বাসযোগ্য়তা প্ৰমাণীকৰণৰ বাবে এপক বায়োমেট্ৰিক হাৰ্ডৱেৰ ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়ে"</string> <string name="permlab_manageFingerprint" msgid="7432667156322821178">"ফিংগাৰপ্ৰিণ্ট হাৰ্ডৱেৰ পৰিচালনা কৰিব পাৰে"</string> <string name="permdesc_manageFingerprint" msgid="2025616816437339865">"ফিংগাৰপ্ৰিণ্ট টেম্প্লেটসমূহ যোগ কৰা বা মচাৰ পদ্ধতিসমূহ কামত লগাবলৈ নিৰ্দেশ দিবলৈ এপটোক অনুমতি দিয়ে।"</string> <string name="permlab_useFingerprint" msgid="1001421069766751922">"ফিংগাৰপ্ৰিণ্ট হাৰ্ডৱেৰ ব্যৱহাৰ কৰিব পাৰে"</string> - <string name="permdesc_useFingerprint" msgid="412463055059323742">"প্ৰমাণীকৰণৰ বাবে ফিংগাৰপ্ৰিণ্ট হাৰ্ডৱেৰ ব্য়ৱহাৰ কৰিবলৈ এপটোক অনুমতি দিয়ে"</string> + <string name="permdesc_useFingerprint" msgid="412463055059323742">"প্ৰমাণীকৰণৰ বাবে ফিংগাৰপ্ৰিণ্ট হাৰ্ডৱেৰ ব্যৱহাৰ কৰিবলৈ এপটোক অনুমতি দিয়ে"</string> <string name="permlab_audioWrite" msgid="8501705294265669405">"আপোনাৰ সংগীত সংগ্ৰহ সালসলনি কৰিবলৈ"</string> <string name="permdesc_audioWrite" msgid="8057399517013412431">"এপক আপোনাৰ সংগীত সংগ্ৰহ সালসলনি কৰিবলৈ দিয়ে।"</string> <string name="permlab_videoWrite" msgid="5940738769586451318">"আপোনাৰ ভিডিঅ’ সংগ্ৰহ সালসলনি কৰিবলৈ"</string> @@ -768,13 +768,13 @@ <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"সর্তকবাণী নিদিয়াকৈয়ে ফেক্টৰী ডেটা ৰিছেট কৰি ইনফ’টেইনমেণ্ট ছিষ্টেমৰ ডেটা মোহাৰক।"</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"সতৰ্কবাণী প্ৰেৰণ নকৰাকৈয়ে ফেক্টৰী ডেটা ৰিছেট কৰি ফ\'নৰ ডেটা মচক।"</string> <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"প্ৰ’ফাইলৰ ডেটা মোহাৰক"</string> - <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"ব্য়ৱহাৰকাৰীৰ তথ্য় মচক"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"ব্য়ৱহাৰকাৰীৰ তথ্য মচক"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"এই টেবলেটটোত থকা এই ব্যৱহাৰকাৰীৰ তথ্য কোনো সর্তকবাণী নিদিয়াকৈ মচি পেলাওক।"</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"কোনো সতর্কবার্তা নপঠিওৱাকৈ এই Android TV ডিভাইচটোত এই ব্যৱহাৰকাৰীৰ ডেটা মচক।"</string> <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"সর্তকবাণী নিদিয়াকৈয়ে এই ইনফ’টেইনমেণ্ট ছিষ্টেমত এই প্ৰ’ফাইলটোৰ ডেটা মোহাৰক।"</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"এই ফ\'নটোত থকা এই ব্যৱহাৰকাৰীৰ তথ্য কোনো সর্তকবাণী নিদিয়াকৈ মচি পেলাওক।"</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"ডিভাইচৰ বাবে গ্ল\'বেল প্ৰক্সী ছেট কৰক"</string> - <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"নীতি সক্ষম কৰি থোৱা অৱস্থাত ব্য়ৱহাৰ কৰিবৰ বাবে ডিভাইচৰ বাবে গ্ল\'বেল প্ৰক্সী ছেট কৰক। কেৱল ডিভাইচৰ গৰাকীয়েহে গ্ল\'বেল প্ৰক্সী ছেট কৰিব পাৰে।"</string> + <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"নীতি সক্ষম কৰি থোৱা অৱস্থাত ব্যৱহাৰ কৰিবৰ বাবে ডিভাইচৰ বাবে গ্ল\'বেল প্ৰক্সী ছেট কৰক। কেৱল ডিভাইচৰ গৰাকীয়েহে গ্ল\'বেল প্ৰক্সী ছেট কৰিব পাৰে।"</string> <string name="policylab_expirePassword" msgid="6015404400532459169">"স্ক্ৰীন লক পাছৱৰ্ডৰ ম্যাদ ওকলাৰ দিন ছেট কৰক"</string> <string name="policydesc_expirePassword" msgid="9136524319325960675">"স্ক্ৰীন লকৰ পাছৱৰ্ড, পিন বা আর্হি কিমান ঘনাই সলনি কৰিব লাগিব তাক সলনি কৰক।"</string> <string name="policylab_encryptedStorage" msgid="9012936958126670110">"ষ্ট’ৰেজৰ এনক্ৰিপশ্বন ছেট কৰক"</string> @@ -1181,7 +1181,7 @@ <string name="whichSendApplicationNamed" msgid="4470386782693183461">"%1$sৰ জৰিয়তে শ্বেয়াৰ কৰক"</string> <string name="whichSendApplicationLabel" msgid="7467813004769188515">"শ্বেয়াৰ কৰক"</string> <string name="whichSendToApplication" msgid="77101541959464018">"ইয়াৰ মাধ্য়মেৰে প্ৰেৰণ কৰক"</string> - <string name="whichSendToApplicationNamed" msgid="3385686512014670003">"%1$s ব্য়ৱহাৰ কৰি প্ৰেৰণ কৰক"</string> + <string name="whichSendToApplicationNamed" msgid="3385686512014670003">"%1$s ব্যৱহাৰ কৰি প্ৰেৰণ কৰক"</string> <string name="whichSendToApplicationLabel" msgid="3543240188816513303">"প্রেৰণ কৰক"</string> <string name="whichHomeApplication" msgid="8276350727038396616">"এটা হ\'ম এপ্ বাছনি কৰক"</string> <string name="whichHomeApplicationNamed" msgid="5855990024847433794">"হ\'ম ৰূপে %1$s ব্যৱহাৰ কৰক"</string> @@ -1464,7 +1464,7 @@ <string name="create_contact_using" msgid="6200708808003692594">"<xliff:g id="NUMBER">%s</xliff:g> ব্যৱহাৰ কৰি সম্পৰ্ক \n সৃষ্টি কৰক"</string> <string name="grant_credentials_permission_message_header" msgid="5365733888842570481">"বৰ্তমান আৰু ভৱিষ্যতে আপোনাৰ একাউণ্টত প্ৰৱেশ কৰিবলৈ তলৰ এটা বা অধিক এপে অনুমতি লাভৰ বাবে অনুৰোধ কৰিছে৷"</string> <string name="grant_credentials_permission_message_footer" msgid="1886710210516246461">"আপুনি এই অনুৰোধক সন্মতি দিব বিচাৰেনে?"</string> - <string name="grant_permissions_header_text" msgid="3420736827804657201">"ব্য়ৱহাৰ কৰাৰ অনুমতি বিচাৰি কৰা অনুৰোধ"</string> + <string name="grant_permissions_header_text" msgid="3420736827804657201">"ব্যৱহাৰ কৰাৰ অনুমতি বিচাৰি কৰা অনুৰোধ"</string> <string name="allow" msgid="6195617008611933762">"অনুমতি দিয়ক"</string> <string name="deny" msgid="6632259981847676572">"প্ৰত্যাখ্যান কৰক"</string> <string name="permission_request_notification_title" msgid="1810025922441048273">"অনুমতি বিচাৰি অনুৰোধ কৰা হৈছে"</string> @@ -1851,7 +1851,7 @@ <string name="confirm_battery_saver" msgid="5247976246208245754">"ঠিক আছে"</string> <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"বেটাৰী সঞ্চয়কাৰীয়ে গাঢ় ৰঙৰ থীম অন কৰে আৰু নেপথ্যৰ কাৰ্যকলাপ, কিছুমান ভিজুৱেল ইফেক্ট, নিৰ্দিষ্ট কিছুমান সুবিধা আৰু নেটৱৰ্কৰ সংযোগ সীমিত অথবা অফ কৰে।"</string> <string name="battery_saver_description" msgid="8518809702138617167">"বেটাৰী সঞ্চয়কাৰীয়ে গাঢ় ৰঙৰ থীম অন কৰে আৰু নেপথ্যৰ কাৰ্যকলাপ, কিছুমান ভিজুৱেল ইফেক্ট, নিৰ্দিষ্ট কিছুমান সুবিধা আৰু নেটৱৰ্কৰ সংযোগ অফ কৰে অথবা সীমাবদ্ধ কৰে।"</string> - <string name="data_saver_description" msgid="4995164271550590517">"ডেটা ব্য়ৱহাৰ হ্ৰাস কৰিবলৈ ডেটা সঞ্চয়কাৰীয়ে কিছুমান এপক নেপথ্য়ত ডেটা প্ৰেৰণ বা সংগ্ৰহ কৰাত বাধা প্ৰদান কৰে। আপুনি বৰ্তমান ব্য়ৱহাৰ কৰি থকা এটা এপে ডেটা এক্সেছ কৰিব পাৰে, কিন্তু সঘনাই এক্সেছ কৰিব নোৱাৰিব পাৰে। ইয়াৰ অৰ্থ উদাহৰণস্বৰূপে এয়া হ\'ব পাৰে যে, আপুনি নিটিপা পর্যন্ত প্ৰতিচ্ছবিসমূহ দেখুওৱা নহ’ব।"</string> + <string name="data_saver_description" msgid="4995164271550590517">"ডেটা ব্যৱহাৰ হ্ৰাস কৰিবলৈ ডেটা সঞ্চয়কাৰীয়ে কিছুমান এপক নেপথ্য়ত ডেটা প্ৰেৰণ বা সংগ্ৰহ কৰাত বাধা প্ৰদান কৰে। আপুনি বৰ্তমান ব্যৱহাৰ কৰি থকা এটা এপে ডেটা এক্সেছ কৰিব পাৰে, কিন্তু সঘনাই এক্সেছ কৰিব নোৱাৰিব পাৰে। ইয়াৰ অৰ্থ উদাহৰণস্বৰূপে এয়া হ\'ব পাৰে যে, আপুনি নিটিপা পর্যন্ত প্ৰতিচ্ছবিসমূহ দেখুওৱা নহ’ব।"</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"ডেটা সঞ্চয়কাৰী অন কৰিবনে?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"অন কৰক"</string> <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{এক মিনিটৰ বাবে ({formattedTime} পৰ্যন্ত)}one{# মিনিটৰ বাবে ({formattedTime} পৰ্যন্ত)}other{# মিনিটৰ বাবে ({formattedTime} পৰ্যন্ত)}}"</string> @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"এই মুহূৰ্তত <xliff:g id="APP_NAME">%1$s</xliff:g> উপলব্ধ নহয়।"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> উপলব্ধ নহয়"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"অনুমতিৰ প্ৰয়োজন"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"কেমেৰা উপলব্ধ নহয়"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"ফ’নতে অব্যাহত ৰাখক"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"মাইক্ৰ’ফ’ন উপলব্ধ নহয়"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TVৰ ছেটিং উপলব্ধ নহয়"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"টেবলেটৰ ছেটিং উপলব্ধ নহয়"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"ফ’নৰ ছেটিং উপলব্ধ নহয়"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"এইটো আপোনাৰ <xliff:g id="DEVICE">%1$s</xliff:g>ত এক্সেছ কৰিব নোৱৰি। তাৰ পৰিৱৰ্তে আপোনাৰ Android TV ডিভাইচত চেষ্টা কৰি চাওক।"</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"এইটো আপোনাৰ <xliff:g id="DEVICE">%1$s</xliff:g>ত এক্সেছ কৰিব নোৱৰি। তাৰ পৰিৱৰ্তে আপোনাৰ টেবলেটত চেষ্টা কৰি চাওক।"</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"এইটো আপোনাৰ <xliff:g id="DEVICE">%1$s</xliff:g>ত এক্সেছ কৰিব নোৱৰি। তাৰ পৰিৱৰ্তে আপোনাৰ ফ’নত চেষ্টা কৰি চাওক।"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"এইটো এই মুহূৰ্তত আপোনাৰ <xliff:g id="DEVICE">%1$s</xliff:g>ত এক্সেছ কৰিব নোৱাৰি। তাৰ পৰিৱৰ্তে আপোনাৰ Android TV ডিভাইচত চেষ্টা কৰি চাওক।"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"এইটো এই মুহূৰ্তত আপোনাৰ <xliff:g id="DEVICE">%1$s</xliff:g>ত এক্সেছ কৰিব নোৱাৰি। তাৰ পৰিৱৰ্তে আপোনাৰ টেবলেটত চেষ্টা কৰি চাওক।"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"এইটো এই মুহূৰ্তত আপোনাৰ <xliff:g id="DEVICE">%1$s</xliff:g>ত এক্সেছ কৰিব নোৱাৰি। তাৰ পৰিৱৰ্তে আপোনাৰ ফ’নত চেষ্টা কৰি চাওক।"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"এই এপ্টোৱে অতিৰিক্ত সুৰক্ষাৰ বাবে অনুৰোধ কৰিছে। তাৰ পৰিৱৰ্তে আপোনাৰ Android TV ডিভাইচত চেষ্টা কৰি চাওক।"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"এই এপ্টোৱে অতিৰিক্ত সুৰক্ষাৰ বাবে অনুৰোধ কৰিছে। তাৰ পৰিৱৰ্তে আপোনাৰ টেবলেটত চেষ্টা কৰি চাওক।"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"এই এপ্টোৱে অতিৰিক্ত সুৰক্ষাৰ বাবে অনুৰোধ কৰিছে। তাৰ পৰিৱৰ্তে আপোনাৰ ফ’নত চেষ্টা কৰি চাওক।"</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"এই এপটো Androidৰ এটা পুৰণা সংস্কৰণৰ বাবে প্ৰস্তুত কৰা হৈছিল, আৰু ই বিচৰাধৰণে কাম নকৰিবও পাৰে। ইয়াৰ আপডে’ট আছে নেকি চাওক, বা বিকাশকৰ্তাৰ সৈতে যোগাযোগ কৰক।"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"আপডে’ট আছে নেকি চাওক"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"আপুনি নতুন বার্তা লাভ কৰিছে"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"অধিক জানিবলৈ আৰু সলনি কৰিবলৈ টিপক।"</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"অসুবিধা নিদিব সলনি হৈছে"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"কি কি অৱৰোধ কৰা হৈছে জানিবলৈ টিপক।"</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"জাননীৰ ছেটিং পৰ্যালোচনা কৰক"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"আপুনি Android 13ত ইনষ্টল কৰা এপক জাননী পঠিয়াবলৈ আপোনাৰ অনুমতিৰ প্ৰয়োজন। আগৰে পৰা থকা এপৰ বাবে এই অনুমতিটো সলনি কৰিবলৈ টিপক।"</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"পাছত মনত পেলাই দিব"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"অগ্ৰাহ্য কৰক"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"ছিষ্টেম"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"ছেটিং"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"কেমেৰা"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> অনুবাদ কৰা হ’ল।"</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"বাৰ্তাটো <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>ৰ পৰা <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>লৈ অনুবাদ কৰা হ’ল।"</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"নেপথ্যত চলি থকা কাৰ্যকলাপ"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"এটা এপে বেটাৰী ব্যৱহাৰ কৰি আছে"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"এটা এপে অত্যধিক বেটাৰি খৰচ কৰি আছে"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"এটা এপ্ এতিয়াও সক্ৰিয় হৈ আছে"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g>এ নেপথ্যত বেটাৰী ব্যৱহাৰ কৰি আছে। পৰ্যালোচনা কৰিবলৈ টিপক।"</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> নেপথ্যত চলি আছে। বেটাৰিৰ ব্যৱহাৰ পৰিচালনা কৰিবলৈ টিপক।"</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g>এ বেটাৰীৰ জীৱনকালৰ ওপৰত প্ৰভাৱ পেলাব পাৰে। সক্ৰিয় এপ্ পৰ্যালোচনা কৰিবলৈ টিপক।"</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"সক্ৰিয় এপ্সমূহ পৰীক্ষা কৰক"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"আপোনাৰ <xliff:g id="DEVICE">%1$s</xliff:g>ৰ পৰা ফ’নটোৰ কেমেৰা এক্সেছ কৰিব নোৱাৰি"</string> diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml index 07f8239269f6..64007d943987 100644 --- a/core/res/res/values-az/strings.xml +++ b/core/res/res/values-az/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> hazırda əlçatan deyil."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> əlçatan deyil"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"İcazə tələb olunur"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kamera əlçatan deyil"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Telefonda davam edin"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofon əlçatan deyil"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV ayarları əlçatan deyil"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Planşet ayarları əlçatan deyil"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Telefon ayarları əlçatan deyil"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"<xliff:g id="DEVICE">%1$s</xliff:g> cihazınızda buna giriş mümkün deyil. Android TV cihazınızda sınayın."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"<xliff:g id="DEVICE">%1$s</xliff:g> cihazınızda buna giriş mümkün deyil. Planşetinizdə sınayın."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"<xliff:g id="DEVICE">%1$s</xliff:g> cihazınızda buna giriş mümkün deyil. Telefonunuzda sınayın."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Hazırda <xliff:g id="DEVICE">%1$s</xliff:g> cihazınızda buna giriş mümkün deyil. Android TV cihazınızda sınayın."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Hazırda <xliff:g id="DEVICE">%1$s</xliff:g> cihazınızda buna giriş mümkün deyil. Planşetinizdə sınayın."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Hazırda <xliff:g id="DEVICE">%1$s</xliff:g> cihazınızda buna giriş mümkün deyil. Telefonunuzda sınayın."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Bu tətbiq əlavə təhlükəsizlik tələb edir. Android TV cihazınızda sınayın."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Bu tətbiq əlavə təhlükəsizlik tələb edir. Planşetinizdə sınayın."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Bu tətbiq əlavə təhlükəsizlik tələb edir. Telefonunuzda sınayın."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Bu tətbiq köhnə Android versiyası üçün hazırlanıb və düzgün işləməyə bilər. Güncəlləməni yoxlayın və ya developer ilə əlaqə saxlayın."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Güncəllənmə olmasını yoxlayın"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Yeni mesajlarınız var"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Ətraflı məıumat əldə edərək dəyişmək üçün klikləyin."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"\"Narahat Etməyin\" rejimi dəyişdirildi"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Nəyin blok edildiyini yoxlamaq üçün klikləyin."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Bildiriş ayarlarını nəzərdən keçirin"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13-də quraşdırdığınız tətbiqlər bildiriş göndərmək üçün icazənizi tələb edir. Mövcud tətbiqlər üçün bu icazəni dəyişmək üçün toxunun."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Sonra xatırladın"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Qapadın"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Sistem"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Ayarlar"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Kamera"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> Tərcümə edildi."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Mesaj <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> dilindən <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> dilinə tərcümə edilib."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Arxa Fonda Fəaliyyət"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Tətbiq batareyadan istifadə edir"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Bir tətbiq batareyanı çox istifadə edir"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Tətbiq hələ də aktivdir"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> arxa fonda batareyadan istifadə edir. Nəzərdən keçirmək üçün toxunun."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> arxa fonda işləyir. Batareya istifadəsini idarə etmək üçün toxunun."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> batareyanın ömrünə təsir edə bilər. Aktiv tətbiqləri nəzərdən keçirmək üçün toxunun."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Aktiv tətbiqləri yoxlayın"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"<xliff:g id="DEVICE">%1$s</xliff:g> cihazınızdan telefonun kamerasına giriş etmək olmur"</string> diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml index 9d645e9dfbbf..117120c44b9a 100644 --- a/core/res/res/values-b+sr+Latn/strings.xml +++ b/core/res/res/values-b+sr+Latn/strings.xml @@ -1934,36 +1934,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutno nije dostupna."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> – nije dostupno"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Potrebna je dozvola"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kamera nije dostupna"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Nastavite na telefonu"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofon je nedostupan"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Podešavanja Android TV-a su nedostupna"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Podešavanja tableta su nedostupna"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Podešavanja telefona su nedostupna"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Ovoj aplikaciji ne može da se pristupi sa uređaja <xliff:g id="DEVICE">%1$s</xliff:g>. Probajte na Android TV uređaju."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Ovoj aplikaciji ne može da se pristupi sa uređaja <xliff:g id="DEVICE">%1$s</xliff:g>. Probajte na tabletu."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Ovoj aplikaciji ne može da se pristupi sa uređaja <xliff:g id="DEVICE">%1$s</xliff:g>. Probajte na telefonu."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Ovoj aplikaciji trenutno ne može da se pristupi sa uređaja <xliff:g id="DEVICE">%1$s</xliff:g>. Probajte na Android TV uređaju."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Ovoj aplikaciji trenutno ne može da se pristupi sa uređaja <xliff:g id="DEVICE">%1$s</xliff:g>. Probajte na tabletu."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Ovoj aplikaciji trenutno ne može da se pristupi sa uređaja <xliff:g id="DEVICE">%1$s</xliff:g>. Probajte na telefonu."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Ova aplikacija zahteva dodatnu bezbednost. Probajte na Android TV uređaju."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Ova aplikacija zahteva dodatnu bezbednost. Probajte na tabletu."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Ova aplikacija zahteva dodatnu bezbednost. Probajte na telefonu."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ova aplikacija je napravljena za stariju verziju Android-a, pa možda neće raditi ispravno. Potražite ažuriranja ili kontaktirajte programera."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Potraži ažuriranje"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Imate nove poruke"</string> @@ -2068,14 +2053,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Dodirnite da biste saznali više i promenili podešavanje."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Režim Ne uznemiravaj je promenjen"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Dodirnite da biste proverili šta je blokirano."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Pregledajte podešavanja obaveštenja"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"U Android-u 13 aplikacije koje instalirate moraju da imaju dozvolu za slanje obaveštenja. Dodirnite da biste promenili ovu dozvolu za postojeće aplikacije."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Podseti me kasnije"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Odbaci"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Sistem"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Podešavanja"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Kamera"</string> @@ -2294,9 +2275,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> Prevedeno."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Poruka je prevedena sa jezika <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> na <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Aktivnost u pozadini"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Aplikacija koristi bateriju"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Aplikacija vam prazni bateriju"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Aplikacija je i dalje aktivna"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> koristi bateriju u pozadini. Dodirnite da biste pregledali."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> radi u pozadini. Dodirnite da biste upravljali potrošnjom baterije."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> može da utiče na trajanje baterije. Dodirnite da biste pregledali aktivne aplikacije."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Proverite aktivne aplikacije"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Ne može da se pristupi kameri telefona sa <xliff:g id="DEVICE">%1$s</xliff:g> uređaja"</string> diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index 66327b569317..4dbd03ca038c 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -1935,36 +1935,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" цяпер недаступная."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"Недаступна: <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Патрабуецца дазвол"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Камера недаступная"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Працягніце на тэлефоне"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Мікрафон недаступны"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Налады Android TV недаступныя"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Налады планшэта недаступныя"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Налады тэлефона недаступныя"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Не ўдаецца атрымаць доступ з прылады \"<xliff:g id="DEVICE">%1$s</xliff:g>\". Паспрабуйце скарыстаць прыладу Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Не ўдаецца атрымаць доступ з прылады \"<xliff:g id="DEVICE">%1$s</xliff:g>\". Паспрабуйце скарыстаць планшэт."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Не ўдаецца атрымаць доступ з прылады \"<xliff:g id="DEVICE">%1$s</xliff:g>\". Паспрабуйце скарыстаць тэлефон."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Не ўдаецца атрымаць доступ з прылады \"<xliff:g id="DEVICE">%1$s</xliff:g>\". Паспрабуйце скарыстаць прыладу Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Не ўдаецца атрымаць доступ з прылады \"<xliff:g id="DEVICE">%1$s</xliff:g>\". Паспрабуйце скарыстаць планшэт."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Не ўдаецца атрымаць доступ з прылады \"<xliff:g id="DEVICE">%1$s</xliff:g>\". Паспрабуйце скарыстаць тэлефон."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Гэтай праграме патрабуецца дадатковая бяспека. Паспрабуйце скарыстаць прыладу Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Гэтай праграме патрабуецца дадатковая бяспека. Паспрабуйце скарыстаць планшэт."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Гэтай праграме патрабуецца дадатковая бяспека. Паспрабуйце скарыстаць тэлефон."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Гэта праграма была створана для больш старой версіі Android і можа не працаваць належным чынам. Праверце наяўнасць абнаўленняў або звярніцеся да распрацоўшчыка."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Праверыць на наяўнасць абнаўленняў"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"У вас ёсць новыя паведамленні"</string> @@ -2069,14 +2054,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Дакраніцеся, каб даведацца больш і змяніць."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Зменены налады рэжыму \"Не турбаваць\""</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Націсніце, каб паглядзець заблакіраванае."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Праверце налады апавяшчэнняў"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"У версіі Android 13 усталяваным вамі праграмам неабходна даць дазвол на адпраўку апавяшчэнняў. Націсніце, каб змяніць дазвол для існуючых праграм."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Нагадаць пазней"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Закрыць"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Сістэма"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Налады"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Камера"</string> @@ -2295,9 +2276,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Паведамленне \"<xliff:g id="MESSAGE">%1$s</xliff:g>\" перакладзена."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Паведамленне перакладзена з мовы \"<xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>\" на мову \"<xliff:g id="TO_LANGUAGE">%2$s</xliff:g>\"."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Фонавая дзейнасць"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Праграма выкарыстоўвае зарад акумулятара"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Праграма па-ранейшаму актыўная"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> выкарыстоўвае зарад акумулятара ў фонавым рэжыме. Націсніце, каб праглядзець."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> можа скараціць час працы прылады ад акумулятара. Націсніце, каб праглядзець актыўныя праграмы."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Праверце актыўныя праграмы"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Не ўдалося атрымаць доступ да камеры тэлефона з прылады \"<xliff:g id="DEVICE">%1$s</xliff:g>\""</string> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index 7cab71d8dfbb..ea5aed4d3cc9 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -1707,7 +1707,7 @@ <string name="accessibility_button_instructional_text" msgid="8853928358872550500">"За превключване между функциите докоснете и задръжте бутона за достъпност."</string> <string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"За превключване между функциите прекарайте два пръста нагоре и задръжте."</string> <string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"За превключване между функциите прекарайте три пръста нагоре и задръжте."</string> - <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Ниво на мащаба"</string> + <string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Увеличение"</string> <string name="user_switched" msgid="7249833311585228097">"Текущ потребител <xliff:g id="NAME">%1$s</xliff:g>."</string> <string name="user_switching_message" msgid="1912993630661332336">"Превключва се към: <xliff:g id="NAME">%1$s</xliff:g>…"</string> <string name="user_logging_out_message" msgid="7216437629179710359">"<xliff:g id="NAME">%1$s</xliff:g> излиза…"</string> @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"В момента няма достъп до <xliff:g id="APP_NAME">%1$s</xliff:g>."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> не е налице"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Необходимо е разрешение"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Няма достъп до камерата"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Продължете на телефона"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Микрофонът не е достъпен"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Настройките за Android TV не са достъпни"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Настройките за таблета не са достъпни"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Настройките за телефона не са достъпни"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Не може да се осъществи достъп от устройството ви <xliff:g id="DEVICE">%1$s</xliff:g>. Вместо това опитайте от устройството си с Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Не може да се осъществи достъп от устройството ви <xliff:g id="DEVICE">%1$s</xliff:g>. Вместо това опитайте от таблета си."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Не може да се осъществи достъп от устройството ви <xliff:g id="DEVICE">%1$s</xliff:g>. Вместо това опитайте от телефона си."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Понастоящем не може да се осъществи достъп от устройството ви <xliff:g id="DEVICE">%1$s</xliff:g>. Вместо това опитайте от устройството си с Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Понастоящем не може да се осъществи достъп от устройството ви <xliff:g id="DEVICE">%1$s</xliff:g>. Вместо това опитайте от таблета си."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Понастоящем не може да се осъществи достъп от устройството ви <xliff:g id="DEVICE">%1$s</xliff:g>. Вместо това опитайте от телефона си."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Това приложение изисква допълнителна стъпка за сигурност. Вместо това опитайте от устройството си с Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Това приложение изисква допълнителна стъпка за сигурност. Вместо това опитайте от таблета си."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Това приложение изисква допълнителна стъпка за сигурност. Вместо това опитайте от телефона си."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Това приложение бе създадено за по-стара версия на Android и може да не работи правилно. Опитайте да проверите за актуализации или се свържете с програмиста."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Проверка за актуализация"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Имате нови съобщения"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Докоснете, за да научите повече и да извършите промени."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Настройките за „Не безпокойте“ са променени"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Докоснете, за да проверите какво е блокирано."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Преглед на настройките за известия"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Под Android 13 инсталираните от вас приложения трябва да получат разрешението ви, за да изпращат известия. Докоснете, за да промените това разрешение за съществуващите приложения."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Напомняне по-късно"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Отхвърляне"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Система"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Настройки"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Камера"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Съобщението <xliff:g id="MESSAGE">%1$s</xliff:g> бе преведено."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Съобщението бе преведено от <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> на <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Активност на заден план"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Приложение използва батерията"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Приложение е все още активно"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> използва батерията на заден план. Докоснете за преглед."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> може да засегне живота на батерията. Докоснете за преглед на активните приложения."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Проверете активните приложения"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Няма достъп до камерата на телефона от вашия <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index 7b6f7708317f..386677c509ed 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"এই মুহূর্তে <xliff:g id="APP_NAME">%1$s</xliff:g> অ্যাপ পাওয়া যাচ্ছে না।"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> উপলভ্য নেই"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"অনুমতি প্রয়োজন"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"ক্যামেরা উপলভ্য নেই"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"ফোনে চালিয়ে যান"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"মাইক্রোফোন উপলভ্য নেই"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV-এর সেটিংস উপলভ্য নেই"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"ট্যাবলেটের সেটিংস উপলভ্য নেই"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"ফোনের সেটিংস উপলভ্য নেই"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"এটি আপনার <xliff:g id="DEVICE">%1$s</xliff:g>-এ অ্যাক্সেস করা যাবে না। পরিবর্তে আপনার Android TV ডিভাইস ব্যবহার করে দেখুন।"</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"এটি আপনার <xliff:g id="DEVICE">%1$s</xliff:g>-এ অ্যাক্সেস করা যাবে না। পরিবর্তে আপনার ট্যাবলেটে ব্যবহার করে দেখুন।"</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"এটি আপনার <xliff:g id="DEVICE">%1$s</xliff:g>-এ অ্যাক্সেস করা যাবে না। পরিবর্তে আপনার ফোনে ব্যবহার করে দেখুন।"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"এই সময়ে আপনার <xliff:g id="DEVICE">%1$s</xliff:g>-এ এটি অ্যাক্সেস করা যাবে না। পরিবর্তে আপনার Android TV ডিভাইস ব্যবহার করে দেখুন।"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"এই সময়ে আপনার <xliff:g id="DEVICE">%1$s</xliff:g>-এ এটি অ্যাক্সেস করা যাবে না। পরিবর্তে আপনার ট্যাবলেটে ব্যবহার করে দেখুন।"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"এই সময়ে আপনার <xliff:g id="DEVICE">%1$s</xliff:g>-এ এটি অ্যাক্সেস করা যাবে না। পরিবর্তে আপনার ফোনে ব্যবহার করে দেখুন।"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"এই অ্যাপ অতিরিক্ত নিরাপত্তার জন্য অনুরোধ করছে। পরিবর্তে আপনার Android TV ডিভাইস ব্যবহার করে দেখুন।"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"এই অ্যাপ অতিরিক্ত নিরাপত্তার জন্য অনুরোধ করছে। পরিবর্তে আপনার ট্যাবলেটে ব্যবহার করে দেখুন।"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"এই অ্যাপ অতিরিক্ত নিরাপত্তার জন্য অনুরোধ করছে। পরিবর্তে আপনার ফোনে ব্যবহার করে দেখুন।"</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"এই অ্যাপটি Android এর একটি পুরনো ভার্সনের জন্য তৈরি করা হয়েছিল, তাই এখানে সেটি ঠিকমতো কাজ নাও করতে পারে। আপডেট পাওয়া যাচ্ছে কিনা দেখুন বা ডেভেলপারের সাথে যোগাযোগ করুন।"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"আপডেট পাওয়া যাচ্ছে কিনা দেখুন"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"আপনার নতুন মেসেজ আছে"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"আরও জানতে এবং পরিবর্তন করতে ট্যাপ করুন।"</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"\'বিরক্ত করবে না\' মোডের সেটিং বদলে গেছে"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"কী কী ব্লক করা আছে তা দেখতে ট্যাপ করুন।"</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"বিজ্ঞপ্তির সেটিংস পর্যালোচনা করুন"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13-এ, আপনার ইনস্টল করা অ্যাপের বিজ্ঞপ্তি পাঠানোর জন্য অনুমতি প্রয়োজন। আগে থাকা অ্যাপের জন্য এই অনুমতি পরিবর্তন করতে ট্যাপ করুন।"</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"পরে মনে করিয়ে দিও"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"বাতিল করুন"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"সিস্টেম"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"সেটিংস"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"ক্যামেরা"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> অনুবাদ করা হয়েছে।"</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"মেসেজ <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> থেকে <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> ভাষাতে অনুবাদ করা হয়েছে।"</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"ব্যাকগ্রাউন্ড অ্যাক্টিভিটি"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"কোনও একটি অ্যাপ ব্যাটারি ব্যবহার করছে"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"কোনও একটি অ্যাপ এখনও চালু আছে"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> ব্যাকগ্রাউন্ডে ব্যাটারি ব্যবহার করছে। পর্যালোচনা করতে ট্যাপ করুন।"</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> ব্যাটারির আয়ুকে প্রভাবিত করতে পারে। চালু থাকা অ্যাপ পর্যালোচনা করতে ট্যাপ করুন।"</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"অ্যাক্টিভ অ্যাপ চেক করুন"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"আপনার <xliff:g id="DEVICE">%1$s</xliff:g> থেকে ফোনের ক্যামেরা অ্যাক্সেস করা যাচ্ছে না"</string> diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml index ad9b770ffeb6..b1b0e05a5594 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -1680,7 +1680,7 @@ <string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"UKLJUČENO"</string> <string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"ISKLJUČENO"</string> <string name="accessibility_enable_service_title" msgid="3931558336268541484">"Dozvoliti da usluga <xliff:g id="SERVICE">%1$s</xliff:g> ima punu kontrolu nad vašim uređajem?"</string> - <string name="accessibility_service_warning_description" msgid="291674995220940133">"Puna kontrola je prikladna za aplikacije koje vam pomažu kod potreba za pristupačnosti, ali nije za većinu aplikacija."</string> + <string name="accessibility_service_warning_description" msgid="291674995220940133">"Puna kontrola je prikladna za aplikacije koje vam pomažu kod potreba pristupačnosti, ali nije za većinu aplikacija."</string> <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"Prikaz i kontrola ekrana"</string> <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Može čitati sav sadržaj na ekranu i prikazivati sadržaj u drugim aplikacijama."</string> <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Prikaz i izvršavanje radnji"</string> @@ -1934,36 +1934,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutno nije dostupna."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"Nedostupno: <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Potrebno je odobrenje"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kamera nije dostupna"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Nastavite na telefonu"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofon nije dostupan"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Postavke Android TV-a nisu dostupne"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Postavke tableta nisu dostupne"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Postavke telefona nisu dostupne"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Ne možete pristupiti ovoj aplikaciji na uređaju <xliff:g id="DEVICE">%1$s</xliff:g>. Umjesto toga pokušajte na uređaju Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Ne možete pristupiti ovoj aplikaciji na uređaju <xliff:g id="DEVICE">%1$s</xliff:g>. Umjesto toga pokušajte na tabletu."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Ne možete pristupiti ovoj aplikaciji na uređaju <xliff:g id="DEVICE">%1$s</xliff:g>. Umjesto toga pokušajte na telefonu."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Trenutno ne možete pristupiti ovoj aplikaciji na uređaju <xliff:g id="DEVICE">%1$s</xliff:g>. Umjesto toga pokušajte na uređaju Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Trenutno ne možete pristupiti ovoj aplikaciji na uređaju <xliff:g id="DEVICE">%1$s</xliff:g>. Umjesto toga pokušajte na tabletu."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Trenutno ne možete pristupiti ovoj aplikaciji na uređaju <xliff:g id="DEVICE">%1$s</xliff:g>. Umjesto toga pokušajte na telefonu."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Ova aplikacija zahtijeva dodatnu sigurnost. Umjesto toga pokušajte na uređaju Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Ova aplikacija zahtijeva dodatnu sigurnost. Umjesto toga pokušajte na tabletu."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Ova aplikacija zahtijeva dodatnu sigurnost. Umjesto toga pokušajte na telefonu."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ova aplikacija je pravljena za stariju verziju Androida i možda neće ispravno raditi. Provjerite jesu li dostupna ažuriranja ili kontaktirajte programera."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Provjeri je li dostupno ažuriranje"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Imate nove poruke"</string> @@ -2068,14 +2053,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Dodirnite da saznate više i izvršite promjene."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Način rada Ne ometaj je promijenjen"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Dodirnite da provjerite šta je blokirano."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Pregledajte postavke obavještenja"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"U Androidu 13 aplikacije koje instalirate trebaju odobrenje da šalju obavještenja. Dodirnite da promijenite odobrenje za postojeće aplikacije."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Podsjeti me kasnije"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Odbaci"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Sistem"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Postavke"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Kamera"</string> @@ -2091,7 +2072,7 @@ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"Uredu"</string> <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Isključi"</string> <string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Saznajte više"</string> - <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Poboljšana obavještenja su zamijenila Prilagodljiva obavještenja Androida u verziji Android 12. Ova funkcija prikazuje predložene radnje i odgovore te organizira vaša obavještenja.\n\nPoboljšana obavještenja mogu pristupiti sadržaju obavještenja, uključujući lične informacije kao što su imena kontakata i poruke. Ova funkcija također može odbacivati obavještenja ili odgovarati na njih, npr. može odgovarati na telefonske pozive i kontrolirati funkciju Ne ometaj."</string> + <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Poboljšana obavještenja su zamijenila Prilagodljiva obavještenja Androida u verziji Android 12. Ova funkcija prikazuje predložene radnje i odgovore te organizira vaša obavještenja.\n\nPoboljšana obavještenja mogu pristupiti sadržaju obavještenja, uključujući lične informacije kao što su imena kontakata i poruke. Ova funkcija također može odbacivati obavještenja ili reagirati na njih, npr. može odgovarati na telefonske pozive i kontrolirati funkciju Ne ometaj."</string> <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Obavještenje za informacije Rutinskog načina"</string> <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Moguće je da će se baterija isprazniti prije uobičajenog punjenja"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Ušteda baterije je aktivirana da bi se produžio vijek trajanja baterije"</string> @@ -2294,9 +2275,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> – prevedeno."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Poruka je prevedena s jezika <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> na <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Aktivnost u pozadini"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Aplikacija koristi bateriju"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Aplikacija prazni bateriju"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Aplikacija je i dalje aktivna"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> koristi bateriju u pozadini. Dodirnite da pregledate."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> se pokreće u pozadini. Dodirnite da biste upravljali potrošnjom baterije."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> može uticati na vijek trajanja baterije. Dodirnite da pregledate aktivne aplikacije."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Provjerite aktivne aplikacije"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Nije moguće pristupiti kameri telefona s uređaja <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index a318064ed22f..c40da7126b50 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"Ara mateix, <xliff:g id="APP_NAME">%1$s</xliff:g> no està disponible."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> no està disponible"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Permís necessari"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"La càmera no està disponible"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Continua al telèfon"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"El micròfon no està disponible"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"La configuració d\'Android TV no està disponible"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"La configuració de la tauleta no està disponible"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"La configuració del telèfon no està disponible"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"No es pot accedir a aquesta aplicació al dispositiu <xliff:g id="DEVICE">%1$s</xliff:g>. Prova-ho al dispositiu Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"No es pot accedir a aquesta aplicació al dispositiu <xliff:g id="DEVICE">%1$s</xliff:g>. Prova-ho a la tauleta."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"No es pot accedir a aquesta aplicació al dispositiu <xliff:g id="DEVICE">%1$s</xliff:g>. Prova-ho al telèfon."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"En aquests moments, no es pot accedir a aquesta aplicació al dispositiu <xliff:g id="DEVICE">%1$s</xliff:g>. Prova-ho al dispositiu Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"En aquests moments, no es pot accedir a aquesta aplicació al dispositiu <xliff:g id="DEVICE">%1$s</xliff:g>. Prova-ho a la tauleta."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"En aquests moments, no es pot accedir a aquesta aplicació al dispositiu <xliff:g id="DEVICE">%1$s</xliff:g>. Prova-ho al telèfon."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Aquesta aplicació sol·licita seguretat addicional. Prova-ho al dispositiu Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Aquesta aplicació sol·licita seguretat addicional. Prova-ho a la tauleta."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Aquesta aplicació sol·licita seguretat addicional. Prova-ho al telèfon."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Aquesta aplicació es va crear per a una versió antiga d\'Android i pot ser que no funcioni correctament. Prova de cercar actualitzacions o contacta amb el desenvolupador."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Cerca actualitzacions"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Tens missatges nous"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Toca per obtenir més informació i canviar la configuració."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"S\'ha canviat el mode No molestis"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Toca per consultar què s\'ha bloquejat."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Consulta la configuració de notificacions"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"A Android 13, les aplicacions que instal·les necessiten el teu permís per enviar notificacions. Toca per canviar aquest permís per a les aplicacions existents."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Recorda-m\'ho més tard"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Ignora"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Sistema"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Configuració"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Càmera"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"S\'ha traduït <xliff:g id="MESSAGE">%1$s</xliff:g>."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Missatge traduït de <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> a <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Activitat en segon pla"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Una aplicació està utilitzant la bateria"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Una aplicació està exhaurint la bateria"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Una aplicació encara està activa"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> està utilitzant la bateria en segon pla. Toca per revisar-ho."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> s\'està executant en segon pla. Toca per gestionar l\'ús de la bateria."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> pot afectar la durada de la bateria. Toca per revisar les aplicacions actives."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Consulta les aplicacions actives"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"No es pot accedir a la càmera del telèfon des del teu <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 067ba2a869c3..bb6a14d2f516 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -1935,36 +1935,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> v tuto chvíli není k dispozici."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> není k dispozici"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Je vyžadováno oprávnění"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kamera není k dispozici"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Pokračujte na telefonu"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofon není k dispozici"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Nastavení Android TV není k dispozici"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Nastavení tabletu není k dispozici"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Nastavení telefonu není k dispozici"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Tato položka na vašem zařízení <xliff:g id="DEVICE">%1$s</xliff:g> není k dispozici. Zkuste to na zařízení Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Tato položka na vašem zařízení <xliff:g id="DEVICE">%1$s</xliff:g> není k dispozici. Zkuste to na tabletu."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Tato položka na vašem zařízení <xliff:g id="DEVICE">%1$s</xliff:g> není k dispozici. Zkuste to na telefonu."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Tato položka na vašem zařízení <xliff:g id="DEVICE">%1$s</xliff:g> v tuto chvíli není k dispozici. Zkuste to na zařízení Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Tato položka na vašem zařízení <xliff:g id="DEVICE">%1$s</xliff:g> v tuto chvíli není k dispozici. Zkuste to na tabletu."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Tato položka na vašem zařízení <xliff:g id="DEVICE">%1$s</xliff:g> v tuto chvíli není k dispozici. Zkuste to na telefonu."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Tato aplikace požaduje další zabezpečení. Zkuste to na zařízení Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Tato aplikace požaduje další zabezpečení. Zkuste to na tabletu."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Tato aplikace požaduje další zabezpečení. Zkuste to na telefonu."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Tato aplikace byla vytvořena pro starší verzi systému Android a nemusí fungovat správně. Zkuste vyhledat aktualizace, případně kontaktujte vývojáře."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Zkontrolovat aktualizace"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Máte nové zprávy"</string> @@ -2069,14 +2054,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Klepnutím zobrazíte další informace a provedete změny."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Nastavení režimu Nerušit se změnilo"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Klepnutím zkontrolujete, co je blokováno."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Zkontrolujte nastavení oznámení"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"V systému Android 13 od vás nainstalované aplikace potřebují oprávnění k odesílání oznámení. Klepnutím toto oprávnění změníte pro stávající aplikace."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Připomenout později"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Zavřít"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Systém"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Nastavení"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Fotoaparát"</string> @@ -2295,9 +2276,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Překlad textu <xliff:g id="MESSAGE">%1$s</xliff:g>."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Zpráva byla přeložena z jazyka <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> do jazyka <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Aktivita na pozadí"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Nějaká aplikace spotřebovává baterii"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Aplikace vybíjí baterii"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Nějaká aplikace je stále aktivní"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"Aplikace <xliff:g id="APP">%1$s</xliff:g> spotřebovává baterii na pozadí. Klepnutím to zkontrolujete."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"Aplikace <xliff:g id="APP">%1$s</xliff:g> běží na pozadí. Klepnutím můžete spravovat využití baterie."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"Aplikace <xliff:g id="APP">%1$s</xliff:g> může ovlivňovat výdrž baterie. Klepnutím zkontrolujete aktivní aplikace."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Zkontrolujte aktivní aplikace"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Ze zařízení <xliff:g id="DEVICE">%1$s</xliff:g> nelze získat přístup k fotoaparátu telefonu"</string> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 63d24e5a1265..879e00160d6b 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> er ikke tilgængelig lige nu."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> er ikke understøttet"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Der kræves tilladelse"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kameraet er ikke tilgængeligt"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Fortsæt på telefonen"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofonen er ikke tilgængelig"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV-indstillingerne er ikke tilgængelige"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Tabletindstillingerne er ikke tilgængelige"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Telefonindstillingerne er ikke tilgængelige"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Du har ikke adgang til denne app på din <xliff:g id="DEVICE">%1$s</xliff:g>. Prøv på din Android TV-enhed i stedet."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Du har ikke adgang til denne app på din <xliff:g id="DEVICE">%1$s</xliff:g>. Prøv på din tablet i stedet."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Du har ikke adgang til denne app på din <xliff:g id="DEVICE">%1$s</xliff:g>. Prøv på din telefon i stedet."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Du har ikke adgang til denne app på din <xliff:g id="DEVICE">%1$s</xliff:g> på nuværende tidspunkt. Prøv på din Android TV-enhed i stedet."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Du har ikke adgang til denne app på din <xliff:g id="DEVICE">%1$s</xliff:g> på nuværende tidspunkt. Prøv på din tablet i stedet."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Du har ikke adgang til denne app på din <xliff:g id="DEVICE">%1$s</xliff:g> på nuværende tidspunkt. Prøv på din telefon i stedet."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Denne app anmoder om yderligere sikkerhed. Prøv på din Android TV-enhed i stedet."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Denne app anmoder om yderligere sikkerhed. Prøv på din tablet i stedet."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Denne app anmoder om yderligere sikkerhed. Prøv på din telefon i stedet."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Denne app er lavet til en ældre version af Android og fungerer muligvis ikke korrekt. Prøv at søge efter opdateringer, eller kontakt udvikleren."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Søg efter opdatering"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Du har nye beskeder"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Tryk for at få flere oplysninger og foretage ændringer."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Tilstanden Forstyr ikke blev ændret"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Tryk for at se, hvad der er blokeret."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Gennemgå indstillinger for notifikationer"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"I Android 13 skal apps, som du installerer, have din tilladelse til at sende notifikationer. Tryk for at ændre denne indstilling for eksisterende apps."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Påmind mig senere"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Luk"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"System"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Indstillinger"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Kamera"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> er oversat."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Meddelelsen er oversat fra <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> til <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Aktivitet i baggrunden"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"En app bruger batteri"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"En app er stadig aktiv"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> bruger batteriet i baggrunden. Tryk for at gennemgå."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> kan påvirke batteritiden. Tryk for at gennemgå nye apps."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Tjek aktive apps"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Kameraet på din telefon kan ikke tilgås via din <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 1cb98c3fb2a6..78e986e5d972 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ist derzeit nicht verfügbar."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> nicht verfügbar"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Berechtigung erforderlich"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kamera nicht verfügbar"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Weiter auf Smartphone"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofon nicht verfügbar"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV-Einstellungen nicht verfügbar"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Tablet-Einstellungen nicht verfügbar"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Smartphone-Einstellungen nicht verfügbar"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Auf deinem <xliff:g id="DEVICE">%1$s</xliff:g> ist kein Zugriff möglich. Versuch es stattdessen auf deinem Android TV-Gerät."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Auf deinem <xliff:g id="DEVICE">%1$s</xliff:g> ist kein Zugriff möglich. Versuch es stattdessen auf deinem Tablet."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Auf deinem <xliff:g id="DEVICE">%1$s</xliff:g> ist kein Zugriff möglich. Versuch es stattdessen auf deinem Smartphone."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Auf deinem <xliff:g id="DEVICE">%1$s</xliff:g> ist derzeit kein Zugriff möglich. Versuch es stattdessen auf deinem Android TV-Gerät."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Auf deinem <xliff:g id="DEVICE">%1$s</xliff:g> ist derzeit kein Zugriff möglich. Versuch es stattdessen auf deinem Tablet."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Auf deinem <xliff:g id="DEVICE">%1$s</xliff:g> ist derzeit kein Zugriff möglich. Versuch es stattdessen auf deinem Smartphone."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Diese App fordert zusätzliche Sicherheit an. Versuch es stattdessen auf deinem Android TV-Gerät."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Diese App fordert zusätzliche Sicherheit an. Versuch es stattdessen auf deinem Tablet."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Diese App fordert zusätzliche Sicherheit an. Versuch es stattdessen auf deinem Smartphone."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Diese App wurde für eine ältere Android-Version entwickelt und funktioniert möglicherweise nicht mehr richtig. Prüfe, ob Updates verfügbar sind oder kontaktiere den Entwickler."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Auf Updates prüfen"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Du hast neue Nachrichten"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Für weitere Informationen und zum Ändern tippen."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"„Bitte nicht stören“ wurde geändert"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Tippe, um zu überprüfen, welche Inhalte blockiert werden."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Benachrichtigungseinstellungen überprüfen"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Bei Android 13 benötigen Apps, die du installierst, die Berechtigung zum Senden von Benachrichtigungen. Wenn du diese Berechtigung für bereits installierte Apps ändern möchtest, tippe hier."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Später erinnern"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Schließen"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"System"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Einstellungen"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Kamera"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"„<xliff:g id="MESSAGE">%1$s</xliff:g>“ wurde übersetzt."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Nachricht wurde von <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> auf <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> übersetzt."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Hintergrundaktivität"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Eine App verbraucht Strom"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Eine App belastet den Akku übermäßig"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Eine App ist immer noch aktiv"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> verwendet im Hintergrund den Akku. Tippe, um die App zu prüfen."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> läuft im Hintergrund. Tippe hier, um die Akkunutzung zu verwalten."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> kann die Akkulaufzeit beeinträchtigen. Tippe, um die aktiven Apps zu prüfen."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Aktive Apps prüfen"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Zugriff auf die Kamera des Smartphones über dein Gerät (<xliff:g id="DEVICE">%1$s</xliff:g>) nicht möglich"</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index 8bc79b714301..fca6363a848f 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> δεν είναι διαθέσιμη αυτήν τη στιγμή."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> δεν διατίθεται"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Απαιτείται άδεια"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Η κάμερα δεν είναι διαθέσιμη"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Συνέχεια στο τηλέφωνο"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Το μικρόφωνο δεν είναι διαθέσιμο"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Οι ρυθμίσεις του Android TV δεν είναι διαθέσιμες"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Οι ρυθμίσεις του tablet δεν είναι διαθέσιμες"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Οι ρυθμίσεις του τηλεφώνου δεν είναι διαθέσιμες"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Δεν είναι δυνατή η πρόσβαση στη συγκεκριμένη εφαρμογή από τη συσκευή <xliff:g id="DEVICE">%1$s</xliff:g>. Δοκιμάστε στη συσκευή Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Δεν είναι δυνατή η πρόσβαση στη συγκεκριμένη εφαρμογή από τη συσκευή <xliff:g id="DEVICE">%1$s</xliff:g>. Δοκιμάστε στο tablet σας."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Δεν είναι δυνατή η πρόσβαση στη συγκεκριμένη εφαρμογή από τη συσκευή <xliff:g id="DEVICE">%1$s</xliff:g>. Δοκιμάστε στο τηλέφωνό σας."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Δεν είναι δυνατή η πρόσβαση στη συγκεκριμένη εφαρμογή από τη συσκευή <xliff:g id="DEVICE">%1$s</xliff:g> αυτήν τη στιγμή. Δοκιμάστε στη συσκευή Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Δεν είναι δυνατή η πρόσβαση στη συγκεκριμένη εφαρμογή από τη συσκευή <xliff:g id="DEVICE">%1$s</xliff:g> αυτήν τη στιγμή. Δοκιμάστε στο tablet σας."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Δεν είναι δυνατή η πρόσβαση στη συγκεκριμένη εφαρμογή από τη συσκευή <xliff:g id="DEVICE">%1$s</xliff:g> αυτήν τη στιγμή. Δοκιμάστε στο τηλέφωνό σας."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Αυτή η εφαρμογή ζητά πρόσθετη ασφάλεια. Δοκιμάστε στη συσκευή Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Αυτή η εφαρμογή ζητά πρόσθετη ασφάλεια. Δοκιμάστε στο tablet σας."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Αυτή η εφαρμογή ζητά πρόσθετη ασφάλεια. Δοκιμάστε στο τηλέφωνό σας."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Αυτή η εφαρμογή δημιουργήθηκε για παλαιότερη έκδοση του Android και μπορεί να μην λειτουργεί σωστά. Δοκιμάστε να ελέγξετε εάν υπάρχουν ενημερώσεις ή επικοινωνήστε με τον προγραμματιστή."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Έλεγχος για ενημέρωση"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Έχετε νέα μηνύματα"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Πατήστε για να μάθετε περισσότερα και να κάνετε αλλαγές."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Η λειτουργία \"Μην ενοχλείτε\" άλλαξε"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Πατήστε για να ελέγξετε το περιεχόμενο που έχει αποκλειστεί."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Έλεγχος ρυθμίσεων ειδοποιήσεων"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Στο Android 13, οι εφαρμογές που εγκαθιστάτε χρειάζονται την άδειά σας για την αποστολή ειδοποιήσεων. Πατήστε για να αλλάξετε αυτήν την άδεια για υπάρχουσες εφαρμογές."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Υπενθύμιση αργότερα"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Παράβλεψη"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Σύστημα"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Ρυθμίσεις"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Κάμερα"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Μεταφράστηκε το μήνυμα <xliff:g id="MESSAGE">%1$s</xliff:g>."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Μήνυμα που έχει μεταφραστεί από τα <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> στα <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Δραστηριότητα στο παρασκήνιο"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Μια εφαρμογή χρησιμοποιεί την μπαταρία"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Μια εφαρμογή εξαντλεί την μπαταρία"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Μια εφαρμογή είναι ακόμα ενεργή"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"Η εφαρμογή <xliff:g id="APP">%1$s</xliff:g> χρησιμοποιεί την μπαταρία στο παρασκήνιο. Πατήστε για έλεγχο."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"Η εφαρμογή <xliff:g id="APP">%1$s</xliff:g> εκτελείται στο παρασκήνιο. Πατήστε για διαχείριση της χρήσης της μπαταρίας."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"Η εφαρμογή <xliff:g id="APP">%1$s</xliff:g> μπορεί να επηρεάσει τη διάρκεια ζωής μπαταρίας. Πατήστε για έλεγχο των ενεργών εφαρμογών."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Έλεγχος ενεργών εφαρμογών"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Δεν είναι δυνατή η πρόσβαση στην κάμερα του τηλεφώνου από τη συσκευή <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index 8374b6acb77a..4b55b70faade 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> unavailable"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Permission needed"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Camera unavailable"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Continue on phone"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Microphone unavailable"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV settings unavailable"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Tablet settings unavailable"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Phone settings unavailable"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g>. Try on your Android TV device instead."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g>. Try on your tablet instead."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g>. Try on your phone instead."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g> at this time. Try on your Android TV device instead."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g> at this time. Try on your tablet instead."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g> at this time. Try on your phone instead."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"This app is requesting additional security. Try on your Android TV device instead."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"This app is requesting additional security. Try on your tablet instead."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"This app is requesting additional security. Try on your phone instead."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"This app was built for an older version of Android and may not work properly. Try checking for updates or contact the developer."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Check for update"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"You have new messages"</string> @@ -2289,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> translated."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Message translated from <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> to <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Background activity"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"An app is using battery"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"An app is draining battery"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"An app is still active"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> is using battery in the background. Tap to review."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> is running in the background. Tap to manage battery usage."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> might affect battery life. Tap to review active apps."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Check active apps"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Can’t access the phone’s camera from your <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index 523d0d305ff8..7ac8f01f3ad1 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> unavailable"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Permission needed"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Camera unavailable"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Continue on phone"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Microphone unavailable"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV settings unavailable"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Tablet settings unavailable"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Phone settings unavailable"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g>. Try on your Android TV device instead."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g>. Try on your tablet instead."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g>. Try on your phone instead."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g> at this time. Try on your Android TV device instead."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g> at this time. Try on your tablet instead."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g> at this time. Try on your phone instead."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"This app is requesting additional security. Try on your Android TV device instead."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"This app is requesting additional security. Try on your tablet instead."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"This app is requesting additional security. Try on your phone instead."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"This app was built for an older version of Android and may not work properly. Try checking for updates or contact the developer."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Check for update"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"You have new messages"</string> @@ -2289,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> translated."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Message translated from <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> to <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Background activity"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"An app is using battery"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"An app is draining battery"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"An app is still active"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> is using battery in the background. Tap to review."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> is running in the background. Tap to manage battery usage."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> might affect battery life. Tap to review active apps."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Check active apps"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Can’t access the phone’s camera from your <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index c3a6ae9e485c..5f3faeb01883 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> unavailable"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Permission needed"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Camera unavailable"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Continue on phone"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Microphone unavailable"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV settings unavailable"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Tablet settings unavailable"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Phone settings unavailable"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g>. Try on your Android TV device instead."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g>. Try on your tablet instead."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g>. Try on your phone instead."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g> at this time. Try on your Android TV device instead."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g> at this time. Try on your tablet instead."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g> at this time. Try on your phone instead."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"This app is requesting additional security. Try on your Android TV device instead."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"This app is requesting additional security. Try on your tablet instead."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"This app is requesting additional security. Try on your phone instead."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"This app was built for an older version of Android and may not work properly. Try checking for updates or contact the developer."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Check for update"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"You have new messages"</string> @@ -2289,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> translated."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Message translated from <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> to <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Background activity"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"An app is using battery"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"An app is draining battery"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"An app is still active"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> is using battery in the background. Tap to review."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> is running in the background. Tap to manage battery usage."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> might affect battery life. Tap to review active apps."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Check active apps"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Can’t access the phone’s camera from your <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index f1241adb51d4..9855d01bfcde 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> unavailable"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Permission needed"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Camera unavailable"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Continue on phone"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Microphone unavailable"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV settings unavailable"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Tablet settings unavailable"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Phone settings unavailable"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g>. Try on your Android TV device instead."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g>. Try on your tablet instead."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g>. Try on your phone instead."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g> at this time. Try on your Android TV device instead."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g> at this time. Try on your tablet instead."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g> at this time. Try on your phone instead."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"This app is requesting additional security. Try on your Android TV device instead."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"This app is requesting additional security. Try on your tablet instead."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"This app is requesting additional security. Try on your phone instead."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"This app was built for an older version of Android and may not work properly. Try checking for updates or contact the developer."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Check for update"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"You have new messages"</string> @@ -2289,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> translated."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Message translated from <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> to <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Background activity"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"An app is using battery"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"An app is draining battery"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"An app is still active"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> is using battery in the background. Tap to review."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> is running in the background. Tap to manage battery usage."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> might affect battery life. Tap to review active apps."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Check active apps"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Can’t access the phone’s camera from your <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml index 03511cc91cfe..05565ae8c8d2 100644 --- a/core/res/res/values-en-rXC/strings.xml +++ b/core/res/res/values-en-rXC/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> unavailable"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Permission needed"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Camera unavailable"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Continue on phone"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Microphone unavailable"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV settings unavailable"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Tablet settings unavailable"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Phone settings unavailable"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g>. Try on your Android TV device instead."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g>. Try on your tablet instead."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g>. Try on your phone instead."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g> at this time. Try on your Android TV device instead."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g> at this time. Try on your tablet instead."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"This can’t be accessed on your <xliff:g id="DEVICE">%1$s</xliff:g> at this time. Try on your phone instead."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"This app is requesting additional security. Try on your Android TV device instead."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"This app is requesting additional security. Try on your tablet instead."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"This app is requesting additional security. Try on your phone instead."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"This app was built for an older version of Android and may not work properly. Try checking for updates, or contact the developer."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Check for update"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"You have new messages"</string> @@ -2289,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> Translated."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Message translated from <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> to <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Background Activity"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"An app is using battery"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"An app is draining battery"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"An app is still active"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> is using battery in the background. Tap to review."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> is running in the background. Tap to manage battery usage."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> might affect battery life. Tap to review active apps."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Check active apps"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Can’t access the phone’s camera from your <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 8c21052241f5..3ed995079e8c 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> no está disponible en este momento."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> no disponible"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Se necesitan permisos"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"La cámara no está disponible"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Continúa en el teléfono"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"El micrófono no está disponible"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"La configuración de Android TV no está disponible"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"La configuración de la tablet no está disponible"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"La configuración del teléfono no está disponible"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Por el momento, no se puede acceder a esto en tu <xliff:g id="DEVICE">%1$s</xliff:g>. Inténtalo en tu dispositivo Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Por el momento, no se puede acceder a esto en tu <xliff:g id="DEVICE">%1$s</xliff:g>. Inténtalo en tu tablet."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Por el momento, no se puede acceder a esto en tu <xliff:g id="DEVICE">%1$s</xliff:g>. Inténtalo en tu teléfono."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Por el momento, no se puede acceder a esto en tu <xliff:g id="DEVICE">%1$s</xliff:g>. Inténtalo en tu dispositivo Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Por el momento, no se puede acceder a esto en tu <xliff:g id="DEVICE">%1$s</xliff:g>. Inténtalo en tu tablet."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Por el momento, no se puede acceder a esto en tu <xliff:g id="DEVICE">%1$s</xliff:g>. Inténtalo en tu teléfono."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Esta app solicita seguridad adicional. Inténtalo en tu dispositivo Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Esta app solicita seguridad adicional. Inténtalo en tu tablet."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Esta app solicita seguridad adicional. Inténtalo en tu teléfono."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Esta app se creó para una versión anterior de Android y es posible que no funcione correctamente. Busca actualizaciones o comunícate con el programador."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Buscar actualización"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Tienes mensajes nuevos"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Presiona para obtener más información y realizar cambios."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Se modificó la opción No interrumpir"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Presiona para consultar lo que está bloqueado."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Revisa la configuración de notificaciones"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"En Android 13, las apps que instales necesitarán tu permiso a fin de enviar notificaciones. Presiona para cambiar este permiso para las apps existentes."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Recordarme más tarde"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Descartar"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Sistema"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Configuración"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Cámara"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Se tradujo: <xliff:g id="MESSAGE">%1$s</xliff:g>."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Se tradujo el mensaje del <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> al <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Actividad en segundo plano"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Una app está consumiendo batería"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Hay una app que sigue activa"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> está consumiendo batería en segundo plano. Presiona para revisar esta actividad."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> podría afectar la duración de la batería. Presiona para revisar las apps activas."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Consulta las apps activas"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"No se puede acceder a la cámara del dispositivo desde tu <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 5eaaec0af8f1..7be37cf9fed4 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"En estos momentos, <xliff:g id="APP_NAME">%1$s</xliff:g> no está disponible."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> no disponible"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Se necesita permiso"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Cámara no disponible"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Continúa en el teléfono"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Micrófono no disponible"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Ajustes de Android TV no disponibles"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Ajustes del tablet no disponibles"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Ajustes del teléfono no disponibles"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"No se puede acceder a este contenido en tu <xliff:g id="DEVICE">%1$s</xliff:g>. Prueba en tu dispositivo Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"No se puede acceder a este contenido en tu <xliff:g id="DEVICE">%1$s</xliff:g>. Prueba en tu tablet."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"No se puede acceder a este contenido en tu <xliff:g id="DEVICE">%1$s</xliff:g>. Prueba en tu teléfono."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"En estos momentos, no se puede acceder a este contenido en tu <xliff:g id="DEVICE">%1$s</xliff:g>. Prueba en tu dispositivo Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"En estos momentos, no se puede acceder a este contenido en tu <xliff:g id="DEVICE">%1$s</xliff:g>. Prueba en tu tablet."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"En estos momentos, no se puede acceder a este contenido en tu <xliff:g id="DEVICE">%1$s</xliff:g>. Prueba en tu teléfono."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Esta aplicación solicita seguridad adicional. Prueba en tu dispositivo Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Esta aplicación solicita seguridad adicional. Prueba en tu tablet."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Esta aplicación solicita seguridad adicional. Prueba en tu teléfono."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Esta aplicación se ha diseñado para una versión anterior de Android y es posible que no funcione correctamente. Busca actualizaciones o ponte en contacto con el desarrollador."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Buscar actualizaciones"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Tienes mensajes nuevos"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Toca para obtener más información y hacer cambios."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Ha cambiado el modo No molestar"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Toca para consultar lo que se está bloqueando."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Consulta los ajustes de notificaciones"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"En Android 13, las aplicaciones que instales necesitan tu permiso para enviar notificaciones. Toca para cambiar este permiso en las aplicaciones que ya tengas."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Recordar más tarde"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Cerrar"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Sistema"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Ajustes"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Cámara"</string> @@ -2090,7 +2071,7 @@ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"Aceptar"</string> <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Desactivar"</string> <string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Más información"</string> - <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Las notificaciones mejoradas sustituyen a las notificaciones adaptativas en Android 12. Esta nueva función te sugiere acciones y respuestas, y organiza tus notificaciones.\n\nLa función puede acceder al contenido de tus notificaciones, incluida información personal, como nombres de contactos y mensajes. También puede cerrar o responder a notificaciones; por ejemplo, puede contestar llamadas telefónicas y controlar el modo No molestar."</string> + <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Las notificaciones mejoradas sustituyeron las notificaciones adaptativas en Android 12. Esta función te muestra acciones y respuestas sugeridas, y organiza tus notificaciones.\n\nLas notificaciones mejoradas pueden acceder al contenido de tus notificaciones, incluida información personal, como nombres de contactos y mensajes. También permiten descartar o responder a notificaciones; por ejemplo, es posible contestar llamadas telefónicas y controlar el modo No molestar."</string> <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notificación sobre el modo rutina"</string> <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Quizás se agote la batería antes de lo habitual"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Se ha activado el modo Ahorro de batería para aumentar la duración de la batería"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> traducido."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Mensaje traducido del <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> al <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Actividad en segundo plano"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Una aplicación está gastando batería"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Una aplicación sigue activa"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> está gastando batería en segundo plano. Toca para ver más detalles."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> podría afectar a la duración de la batería. Toca para ver las aplicaciones activas."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Consultar aplicaciones activas"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"No se puede acceder a la cámara del teléfono desde tu <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml index 99e7ba359235..6e6349f26bdd 100644 --- a/core/res/res/values-et/strings.xml +++ b/core/res/res/values-et/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ei ole praegu saadaval."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ei ole saadaval"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Vaja on luba"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kaamera pole saadaval"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Jätkake telefonis"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofon pole saadaval"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV seaded pole saadaval"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Tahvelarvuti seaded pole saadaval"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Telefoni seaded pole saadaval"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Sellele ei pääse teie seadmes <xliff:g id="DEVICE">%1$s</xliff:g> juurde. Proovige juurde pääseda oma Android TV seadmes."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Sellele ei pääse teie seadmes <xliff:g id="DEVICE">%1$s</xliff:g> juurde. Proovige juurde pääseda oma tahvelarvutis."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Sellele ei pääse teie seadmes <xliff:g id="DEVICE">%1$s</xliff:g> juurde. Proovige juurde pääseda oma telefonis."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Sellele ei pääse praegu teie seadmes <xliff:g id="DEVICE">%1$s</xliff:g> juurde. Proovige juurde pääseda oma Android TV seadmes."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Sellele ei pääse praegu teie seadmes <xliff:g id="DEVICE">%1$s</xliff:g> juurde. Proovige juurde pääseda oma tahvelarvutis."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Sellele ei pääse praegu teie seadmes <xliff:g id="DEVICE">%1$s</xliff:g> juurde. Proovige juurde pääseda oma telefonis."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"See rakendus nõuab lisaturvalisust. Proovige juurde pääseda oma Android TV seadmes."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"See rakendus nõuab lisaturvalisust. Proovige juurde pääseda oma tahvelarvutis."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"See rakendus nõuab lisaturvalisust. Proovige juurde pääseda oma telefonis."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"See rakendus on loodud Androidi vanema versiooni jaoks ega pruugi õigesti töötada. Otsige värskendusi või võtke ühendust arendajaga."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Otsi värskendust"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Teile on uusi sõnumeid"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Puudutage lisateabe vaatamiseks ja muutmiseks."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Režiimi Mitte segada muudeti"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Puudutage, et kontrollida, mis on blokeeritud."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Vaadake üle märguandeseaded"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Operatsioonisüsteemis Android 13 vajavad installitavad rakendused märguannete saatmiseks teie luba. Puudutage, et muuta seda luba olemasolevate rakenduste jaoks."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Tuleta hiljem meelde"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Loobu"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Süsteem"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Seaded"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Kaamera"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Sõnum „<xliff:g id="MESSAGE">%1$s</xliff:g>” on tõlgitud."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Sõnum on tõlgitud <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> keelest <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> keelde."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Tegevus taustal"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Rakendus kasutab akutoidet"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Rakendus on ikka aktiivne"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> kasutab taustal akutoidet. Puudutage ülevaatamiseks."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> võib aku tööiga mõjutada. Puudutage aktiivsete rakenduste ülevaatamiseks."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Vaadake aktiivseid rakendusi"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Teie seadmest <xliff:g id="DEVICE">%1$s</xliff:g> ei pääse telefoni kaamerale juurde"</string> diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index a7412ba554f3..497df3a8c4f1 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -54,7 +54,7 @@ <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> saiakera geratzen zaizkizu SIM txartela blokeatu aurretik.</item> <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> saiakera geratzen zaizu SIM txartela blokeatu aurretik.</item> </plurals> - <string name="imei" msgid="2157082351232630390">"IMEI zk."</string> + <string name="imei" msgid="2157082351232630390">"IMEIa"</string> <string name="meid" msgid="3291227361605924674">"MEID"</string> <string name="ClipMmi" msgid="4110549342447630629">"Sarrerako deien identifikazio-zerbitzua"</string> <string name="ClirMmi" msgid="6752346475055446417">"Ezkutatu irteerako deitzailearen IDa"</string> @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ez dago erabilgarri une honetan."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ez dago erabilgarri"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Baimena behar da"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kamera ez dago erabilgarri"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Jarraitu telefonoan"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofonoa ez dago erabilgarri"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV-ren ezarpenak ez daude erabilgarri"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Tabletaren ezarpenak ez daude erabilgarri"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Telefonoaren ezarpenak ez daude erabilgarri"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Aplikazioa ezin da <xliff:g id="DEVICE">%1$s</xliff:g> erabilita atzitu. Gailu horren ordez, erabili Android TV darabilen bat."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Aplikazioa ezin da <xliff:g id="DEVICE">%1$s</xliff:g> erabilita atzitu. Gailu horren ordez, erabili tableta."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Aplikazioa ezin da <xliff:g id="DEVICE">%1$s</xliff:g> erabilita atzitu. Gailu horren ordez, erabili telefonoa."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Une honetan, aplikazioa ezin da <xliff:g id="DEVICE">%1$s</xliff:g> erabilita atzitu. Gailu horren ordez, erabili Android TV darabilen bat."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Une honetan, aplikazioa ezin da <xliff:g id="DEVICE">%1$s</xliff:g> erabilita atzitu. Gailu horren ordez, erabili tableta."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Une honetan, aplikazioa ezin da <xliff:g id="DEVICE">%1$s</xliff:g> erabilita atzitu. Gailu horren ordez, erabili telefonoa."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Segurtasun gehigarria eskatzen ari da aplikazioa. Gailu horren ordez, erabili Android TV darabilen bat."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Segurtasun gehigarria eskatzen ari da aplikazioa. Gailu horren ordez, erabili tableta."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Segurtasun gehigarria eskatzen ari da aplikazioa. Gailu horren ordez, erabili telefonoa."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Aplikazioa Android-en bertsio zaharrago baterako sortu zenez, baliteke behar bezala ez funtzionatzea. Bilatu eguneratzerik baden, edo jarri garatzailearekin harremanetan."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Bilatu eguneratzeak"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Mezu berriak dituzu"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Sakatu informazio gehiago lortzeko eta portaera aldatzeko."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Ez molestatzeko modua aldatu da"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Sakatu zer dagoen blokeatuta ikusteko."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Berrikusi jakinarazpen-ezarpenak"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13-n, jakinarazpenak bidaltzeko baimena eman behar diezu instalatzen dituzun aplikazioei. Sakatu hau lehendik dauden aplikazioen baimenak aldatzeko."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Gogorarazi geroago"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Baztertu"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Sistema"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Ezarpenak"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Kamera"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Itzuli da <xliff:g id="MESSAGE">%1$s</xliff:g>."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"<xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> hizkuntzatik <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> hizkuntzara itzuli da mezua."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Atzeko planoko jarduerak"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Aplikazio bat bateria erabiltzen ari da"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Aplikazio bat aktibo dago oraindik"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> atzeko planoan bateria erabiltzen ari da. Sakatu berrikusteko."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"Baliteke <xliff:g id="APP">%1$s</xliff:g> aplikazioak bateriaren iraupenean eragina izatea. Sakatu hau aplikazio aktiboak ikusteko."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Ikusi zer aplikazio dauden aktibo"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Ezin da atzitu telefonoaren kamera <xliff:g id="DEVICE">%1$s</xliff:g> gailutik"</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index 8519c43bae78..d1af2cd8b3aa 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> درحالحاضر در دسترس نیست."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> دردسترس نیست"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"اجازه لازم است"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"دوربین دردسترس نیست"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"ادامه دادن در تلفن"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"میکروفون دردسترس نیست"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"تنظیمات Android TV دردسترس نیست"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"تنظیمات رایانه لوحی دردسترس نیست"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"تنظیمات تلفن دردسترس نیست"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"نمیتوان در <xliff:g id="DEVICE">%1$s</xliff:g> به این برنامه دسترسی داشت. دسترسی به آن را در دستگاه Android TV امتحان کنید."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"نمیتوان در <xliff:g id="DEVICE">%1$s</xliff:g> به این برنامه دسترسی داشت. دسترسی به آن را در رایانه لوحیتان امتحان کنید."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"نمیتوان در <xliff:g id="DEVICE">%1$s</xliff:g> به این برنامه دسترسی داشت. دسترسی به آن را در تلفنتان امتحان کنید."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"درحالحاضر نمیتوانید در <xliff:g id="DEVICE">%1$s</xliff:g> به این برنامه دسترسی داشت. دسترسی به آن را در دستگاه Android TV امتحان کنید."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"درحالحاضر نمیتوانید در <xliff:g id="DEVICE">%1$s</xliff:g> به این برنامه دسترسی داشت. دسترسی به آن را در رایانه لوحیتان امتحان کنید."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"درحالحاضر نمیتوانید در <xliff:g id="DEVICE">%1$s</xliff:g> به این برنامه دسترسی داشت. دسترسی به آن را در تلفنتان امتحان کنید."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"این برنامه درخواست امنیت اضافی دارد. دسترسی به آن را در دستگاه Android TV امتحان کنید."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"این برنامه درخواست امنیت اضافی دارد. دسترسی به آن را در رایانه لوحیتان امتحان کنید."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"این برنامه درخواست امنیت اضافی دارد. دسترسی به آن را در تلفنتان امتحان کنید."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"این برنامه برای نسخه قدیمیتری از Android ساخته شده است و ممکن است درست کار نکند. وجود بهروزرسانی را بررسی کنید یا با برنامهنویس تماس بگیرید."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"بررسی وجود بهروزرسانی"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"پیامهای جدیدی دارید"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"برای اطلاعات بیشتر و تغییر دادن، ضربه بزنید."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"«مزاحم نشوید» تغییر کرده است"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"برای بررسی موارد مسدودشده ضربه بزنید."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"مرور تنظیمات اعلان"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"در Android نسخه ۱۳، برنامههایی که نصب میکنید برای ارسال اعلان به اجازه شما نیاز دارند. برای تغییر دادن این اجازه برای برنامههای موجود، ضربه بزنید."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"بعداً یادآوری شود"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"رد شدن"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"سیستم"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"تنظیمات"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"دوربین"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> ترجمه شد."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"پیام از <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> به <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> ترجمه شد."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"فعالیت در پسزمینه"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"یکی از برنامهها درحال مصرف شارژ باتری است"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"یکی از برنامهها همچنان فعال است"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> در پسزمینه از شارژ باتری استفاده میکند. برای مرور، ضربه بزنید."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> ممکن است بر عمر باتری تأثیر بگذارد. برای مرور برنامههای فعال، ضربه بزنید."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"بررسی برنامههای فعال"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"نمیتوان از <xliff:g id="DEVICE">%1$s</xliff:g> شما به دوربین تلفن دسترسی داشت"</string> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index 70398588792c..adea5bf0838c 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -1679,7 +1679,7 @@ <string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"PÄÄLLÄ"</string> <string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"EI PÄÄLLÄ"</string> <string name="accessibility_enable_service_title" msgid="3931558336268541484">"Saako <xliff:g id="SERVICE">%1$s</xliff:g> laitteesi täyden käyttöoikeuden?"</string> - <string name="accessibility_service_warning_description" msgid="291674995220940133">"Täysi käyttöoikeus sopii esteettömyyssovelluksille, mutta ei useimmille sovelluksille."</string> + <string name="accessibility_service_warning_description" msgid="291674995220940133">"Täysi käyttöoikeus sopii saavutettavuussovelluksille, mutta ei useimmille sovelluksille."</string> <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"Näytön katselu ja ohjaus"</string> <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Se voi lukea kaiken näytön sisällön ja näyttää sisältöä kaikista sovelluksista."</string> <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Toimintojen näkeminen ja suorittaminen"</string> @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ei ole nyt käytettävissä."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ei käytettävissä"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Edellyttää käyttöoikeutta"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kamera ei käytettävissä"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Jatka puhelimella"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofoni ei ole käytettävissä"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV:n asetukset eivät ole käytettävissä"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Tabletin asetukset eivät ole käytettävissä"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Puhelimen asetukset eivät ole käytettävissä"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"<xliff:g id="DEVICE">%1$s</xliff:g> ei saa pääsyä sovellukseen. Kokeile striimausta Android TV ‑laitteella."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"<xliff:g id="DEVICE">%1$s</xliff:g> ei saa pääsyä sovellukseen. Kokeile striimausta tabletilla."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"<xliff:g id="DEVICE">%1$s</xliff:g> ei saa pääsyä sovellukseen. Kokeile striimausta puhelimella."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"<xliff:g id="DEVICE">%1$s</xliff:g> ei tällä hetkellä saa pääsyä sovellukseen. Kokeile striimausta Android TV ‑laitteella."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"<xliff:g id="DEVICE">%1$s</xliff:g> ei tällä hetkellä saa pääsyä sovellukseen. Kokeile striimausta tabletilla."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"<xliff:g id="DEVICE">%1$s</xliff:g> ei tällä hetkellä saa pääsyä sovellukseen. Kokeile striimausta puhelimella."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Sovellus pyytää lisäsuojausta. Kokeile striimausta Android TV ‑laitteella."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Sovellus pyytää lisäsuojausta. Kokeile striimausta tabletilla."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Sovellus pyytää lisäsuojausta. Kokeile striimausta puhelimella."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Tämä sovellus on suunniteltu vanhemmalle Android-versiolle eikä välttämättä toimi oikein. Kokeile tarkistaa päivitykset tai ottaa yhteyttä kehittäjään."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Tarkista päivitykset"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Sinulle on uusia viestejä"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Napauta, jos haluat lukea lisää ja tehdä muutoksia."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Älä häiritse ‑tila muuttui"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Napauta niin näet, mitä on estetty."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Tarkista ilmoitusasetukset"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Asentamasi sovellukset tarvitsevat sinulta luvan ilmoitusten lähettämiseen Android 13 ‑käyttöjärjestelmässä. Napauta muuttaaksesi aiempien sovellusten lupia."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Muistuta myöhemmin"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Ohita"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Järjestelmä"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Asetukset"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Kamera"</string> @@ -2134,7 +2115,7 @@ <string name="accessibility_system_action_headset_hook_label" msgid="8524691721287425468">"Kuulokemikrofonin koukku"</string> <string name="accessibility_system_action_on_screen_a11y_shortcut_label" msgid="8488701469459210309">"Näytöllä näkyvä esteettömyyspainike"</string> <string name="accessibility_system_action_on_screen_a11y_shortcut_chooser_label" msgid="1057878690209817886">"Näytöllä näkyvän esteettömyyspainikkeen valitsin"</string> - <string name="accessibility_system_action_hardware_a11y_shortcut_label" msgid="5764644187715255107">"Esteettömyyspainike"</string> + <string name="accessibility_system_action_hardware_a11y_shortcut_label" msgid="5764644187715255107">"Saavutettavuuspainike"</string> <string name="accessibility_system_action_dismiss_notification_shade" msgid="8931637495533770352">"Sulje ilmoitusalue"</string> <string name="accessibility_system_action_dpad_up_label" msgid="1029042950229333782">"Suuntanäppäimistö: ylös-painike"</string> <string name="accessibility_system_action_dpad_down_label" msgid="3441918448624921461">"Suuntanäppäimisto: alas-painike"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> käännettiin."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Viesti käännettiin kielestä <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> kielelle <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Taustatoiminta"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Sovellus käyttää akkua"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Sovellus on edelleen aktiivinen"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> käyttää akkua taustalla. Tarkista napauttamalla."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> saattaa vaikuttaa akunkestoon. Tarkista aktiiviset sovellukset napauttamalla."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Tarkista aktiiviset sovellukset"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"<xliff:g id="DEVICE">%1$s</xliff:g> ei pääse puhelimen kameraan"</string> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index cb41aab61689..71bd100d7dbf 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas accessible pour le moment."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> non accessible"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Autorisation nécessaire"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Appareil photo non accessible"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Continuer sur le téléphone"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Microphone non accessible"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Paramètres Android TV non accessibles"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Paramètres de la tablette non accessibles"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Paramètres du téléphone non accessibles"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Impossible d\'accéder à ce contenu sur votre appareil <xliff:g id="DEVICE">%1$s</xliff:g>. Essayez sur votre appareil Android TV à la place."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Impossible d\'accéder à ce contenu sur votre appareil <xliff:g id="DEVICE">%1$s</xliff:g>. Essayez sur votre tablette à la place."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Impossible d\'accéder à ce contenu sur votre appareil <xliff:g id="DEVICE">%1$s</xliff:g>. Essayez sur votre téléphone à la place."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Impossible d\'accéder à ce contenu sur votre appareil <xliff:g id="DEVICE">%1$s</xliff:g> pour le moment. Essayez sur votre appareil Android TV à la place."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Impossible d\'accéder à ce contenu sur votre appareil <xliff:g id="DEVICE">%1$s</xliff:g> pour le moment. Essayez sur votre tablette à la place."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Impossible d\'accéder à ce contenu sur votre appareil <xliff:g id="DEVICE">%1$s</xliff:g> pour le moment. Essayez sur votre téléphone à la place."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Cette application demande une sécurité supplémentaire. Essayez sur votre appareil Android TV à la place."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Cette application demande une sécurité supplémentaire. Essayez sur votre tablette à la place."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Cette application demande une sécurité supplémentaire. Essayez sur votre téléphone à la place."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Cette application a été conçue pour une ancienne version d\'Android et pourrait ne pas fonctionner correctement. Essayez de vérifier les mises à jour ou communiquez avec son développeur."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Vérifier la présence de mises à jour"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Vous avez de nouveaux messages"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Touchez ici pour en savoir plus et changer les paramètres"</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Les paramètres du mode Ne pas déranger ont changé"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Touchez l\'écran pour vérifier ce qui est bloqué."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Examiner les paramètres de notification"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Sous Android 13, les applications que vous installez ont besoin de votre autorisation pour envoyer des notifications. Touchez pour modifier cette autorisation pour les applications existantes."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Me rappeler plus tard"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Fermer"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Système"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Paramètres"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Appareil photo"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Message <xliff:g id="MESSAGE">%1$s</xliff:g> traduit."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Message traduit : <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> vers <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Activité en arrière-plan"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Une application consomme de l\'énergie"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Une application est toujours active"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> consomme de l\'énergie en arrière-plan. Touchez pour examiner."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> peut avoir une incidence sur l\'autonomie de la pile. Touchez pour examiner les applications actives."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Vérifier les applications actives"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Impossible d\'accéder à l\'appareil photo du téléphone à partir de votre <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index 14134b86655e..0675e8c00dc4 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas disponible pour le moment."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> indisponible"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Autorisation nécessaire"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Caméra indisponible"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Continuez sur le téléphone"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Micro indisponible"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Paramètres Android TV indisponibles"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Paramètres de la tablette indisponibles"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Paramètres du téléphone indisponibles"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Impossible d\'accéder à cette application sur votre <xliff:g id="DEVICE">%1$s</xliff:g>. Essayez plutôt d\'y accéder sur votre appareil Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Impossible d\'accéder à cette application sur votre <xliff:g id="DEVICE">%1$s</xliff:g>. Essayez plutôt d\'y accéder sur votre tablette."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Impossible d\'accéder à cette application sur votre <xliff:g id="DEVICE">%1$s</xliff:g>. Essayez plutôt d\'y accéder sur votre téléphone."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Vous ne pouvez pas accéder à cette appli sur votre <xliff:g id="DEVICE">%1$s</xliff:g> pour le moment. Essayez plutôt d\'y accéder sur votre appareil Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Vous ne pouvez pas accéder à cette appli sur votre <xliff:g id="DEVICE">%1$s</xliff:g> pour le moment. Essayez plutôt d\'y accéder sur votre tablette."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Vous ne pouvez pas accéder à cette appli sur votre <xliff:g id="DEVICE">%1$s</xliff:g> pour le moment. Essayez plutôt d\'y accéder sur votre téléphone."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Cette appli demande une sécurité supplémentaire. Essayez plutôt d\'y accéder sur votre appareil Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Cette appli demande une sécurité supplémentaire. Essayez plutôt d\'y accéder sur votre tablette."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Cette appli demande une sécurité supplémentaire. Essayez plutôt d\'y accéder sur votre téléphone."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Cette application a été conçue pour une ancienne version d\'Android et risque de ne pas fonctionner correctement. Recherchez des mises à jour ou contactez le développeur."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Rechercher une mise à jour"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Vous avez de nouveaux messages"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Appuyez pour en savoir plus et pour modifier les paramètres."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Le mode Ne pas déranger a été modifié"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Appuyez pour vérifier les contenus bloqués."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Consulter les paramètres de notification"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Sur Android 13, les applis que vous installez ont besoin de votre autorisation pour vous envoyer des notifications. Appuyez pour modifier cette autorisation pour les applis déjà installées."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Plus tard"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Fermer"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Système"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Paramètres"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Caméra"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> traduit."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Message en <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> traduit en <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Activité en arrière-plan"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Une appli utilise la batterie"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Une appli est encore active"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> utilise la batterie en arrière-plan. Appuyez pour en savoir plus."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> peut affecter l\'autonomie de la batterie. Appuyez pour consulter les applis actives."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Vérifier les applis actives"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Impossible d\'accéder à l\'appareil photo du téléphone depuis votre <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml index 8641fc1b617d..6cadfa1a4d66 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -425,9 +425,9 @@ <string name="permdesc_writeCallLog" product="tablet" msgid="2657525794731690397">"Permite á aplicación modificar o rexistro de chamadas da tableta, incluídos os datos acerca de chamadas entrantes e saíntes. É posible que aplicacións maliciosas utilicen esta acción para borrar ou modificar o teu rexistro de chamadas."</string> <string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"Permite que a aplicación modifique o rexistro de chamadas do dispositivo Android TV, incluídos os datos acerca de chamadas entrantes e saíntes. As aplicacións maliciosas poden utilizar este permiso para borrar ou modificar o rexistro de chamadas."</string> <string name="permdesc_writeCallLog" product="default" msgid="5903033505665134802">"Permite á aplicación modificar o rexistro de chamadas do teléfono, incluídos os datos acerca de chamadas entrantes e saíntes. É posible que aplicacións maliciosas utilicen esta acción para borrar ou modificar o teu rexistro de chamadas."</string> - <string name="permlab_bodySensors" msgid="662918578601619569">"Acceso aos datos dos sensores corporais, como o ritmo cardíaco, mentres se use"</string> - <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Permite que a aplicación acceda aos datos dos sensores corporais (por exemplo, o ritmo cardíaco, a temperatura ou a porcentaxe de osíxeno en sangue) mentres se estea utilizando."</string> - <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Acceso en segundo plano aos datos dos sensores corporais, como o ritmo cardíaco"</string> + <string name="permlab_bodySensors" msgid="662918578601619569">"Acceso aos datos dos sensores corporais, como a frecuencia cardíaca, mentres se use"</string> + <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Permite que a aplicación acceda aos datos dos sensores corporais (por exemplo, a frecuencia cardíaca, a temperatura ou a porcentaxe de osíxeno en sangue) mentres se estea utilizando."</string> + <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Acceso en segundo plano aos datos dos sensores corporais, como a frecuencia cardíaca"</string> <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Permite que a aplicación acceda aos datos dos sensores corporais (por exemplo, a frecuencia cardíaca, a temperatura ou a porcentaxe de osíxeno en sangue) mentres se estea executando en segundo plano."</string> <string name="permlab_readCalendar" msgid="6408654259475396200">"Ler os detalles e os eventos do calendario"</string> <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Esta aplicación pode ler todos os eventos do calendario almacenados na túa tableta e compartir ou gardar os datos do calendario."</string> @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"A aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> non está dispoñible neste momento."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> non está dispoñible"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Necesítase permiso"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"A cámara non está dispoñible"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Continúa no teléfono"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"O micrófono non está dispoñible"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"A configuración de Android TV non está dispoñible"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"A configuración da tableta non está dispoñible"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"A configuración do teléfono non está dispoñible"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Non se puido acceder a este contido desde o teu dispositivo (<xliff:g id="DEVICE">%1$s</xliff:g>). Proba a facelo desde o dispositivo con Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Non se puido acceder a este contido desde o teu dispositivo (<xliff:g id="DEVICE">%1$s</xliff:g>). Proba a facelo desde a tableta."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Non se puido acceder a este contido desde o teu dispositivo (<xliff:g id="DEVICE">%1$s</xliff:g>). Proba a facelo desde o teléfono."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Nestes momentos, non podes acceder a este contido desde o teu dispositivo (<xliff:g id="DEVICE">%1$s</xliff:g>). Proba a facelo desde o dispositivo con Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Nestes momentos, non podes acceder a este contido desde o teu dispositivo (<xliff:g id="DEVICE">%1$s</xliff:g>). Proba a facelo desde a tableta."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Nestes momentos, non podes acceder a este contido desde o teu dispositivo (<xliff:g id="DEVICE">%1$s</xliff:g>). Proba a facelo desde o teléfono."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Esta aplicación solicita seguranza adicional. Proba a facelo desde o dispositivo con Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Esta aplicación solicita seguranza adicional. Proba a facelo desde a tableta."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Esta aplicación solicita seguranza adicional. Proba a facelo desde o teléfono."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Esta aplicación deseñouse para unha versión anterior de Android e quizais non funcione correctamente. Proba a buscar actualizacións ou contacta co programador."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Buscar actualización"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Tes mensaxes novas"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Toca para obter máis información e facer cambios."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"O modo Non molestar cambiou"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Toca para comprobar o contido bloqueado."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Consulta a configuración de notificacións"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"En Android 13, as aplicacións que instales necesitan o teu permiso para enviar notificacións. Toca para cambiar este permiso nas aplicacións que xa teñas."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Lembrarmo máis tarde"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Pechar"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Sistema"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Configuración"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Cámara"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Mensaxe <xliff:g id="MESSAGE">%1$s</xliff:g> traducida."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Mensaxe traducida do <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> ao <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Actividade en segundo plano"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Hai unha aplicación consumindo batería"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Hai unha aplicación que aínda está activa"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> está consumindo batería en segundo plano. Toca para revisalo."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> podería estar minguando a duración da batería. Toca para revisar as aplicacións activas."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Comprobar aplicacións activas"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Non se puido acceder á cámara do teléfono desde o teu dispositivo (<xliff:g id="DEVICE">%1$s</xliff:g>)"</string> diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml index 2d34b8ee81e7..43f21d48c4d4 100644 --- a/core/res/res/values-gu/strings.xml +++ b/core/res/res/values-gu/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> હાલમાં ઉપલબ્ધ નથી."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ઉપલબ્ધ નથી"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"પરવાનગી જરૂરી છે"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"કૅમેરા ઉપલબ્ધ નથી"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"ફોન પર ચાલુ રાખો"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"માઇક્રોફોન ઉપલબ્ધ નથી"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV સેટિંગ ઉપલબ્ધ નથી"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"ટૅબ્લેટ સેટિંગ ઉપલબ્ધ નથી"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"ફોન સેટિંગ ઉપલબ્ધ નથી"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"આને તમારા <xliff:g id="DEVICE">%1$s</xliff:g> પર ઍક્સેસ કરી શકાતી નથી. તેના બદલે તમારા Android TV ડિવાઇસ પર પ્રયાસ કરો."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"આને તમારા <xliff:g id="DEVICE">%1$s</xliff:g> પર ઍક્સેસ કરી શકાતી નથી. તેના બદલે તમારા ટૅબ્લેટ પર પ્રયાસ કરો."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"આને તમારા <xliff:g id="DEVICE">%1$s</xliff:g> પર ઍક્સેસ કરી શકાતી નથી. તેના બદલે તમારા ફોન પર પ્રયાસ કરો."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"અત્યારે આને તમારા <xliff:g id="DEVICE">%1$s</xliff:g> પર ઍક્સેસ કરી શકાતી નથી. તેના બદલે તમારા Android TV ડિવાઇસ પર પ્રયાસ કરો."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"અત્યારે આને તમારા <xliff:g id="DEVICE">%1$s</xliff:g> પર ઍક્સેસ કરી શકાતી નથી. તેના બદલે તમારા ટૅબ્લેટ પર પ્રયાસ કરો."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"અત્યારે આને તમારા <xliff:g id="DEVICE">%1$s</xliff:g> પર ઍક્સેસ કરી શકાતી નથી. તેના બદલે તમારા ફોન પર પ્રયાસ કરો."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"આ ઍપ દ્વારા વધારાની સુરક્ષાની વિનંતી કરવામાં આવી રહી છે. તેના બદલે તમારા Android TV ડિવાઇસ પર પ્રયાસ કરો."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"આ ઍપ દ્વારા વધારાની સુરક્ષાની વિનંતી કરવામાં આવી રહી છે. તેના બદલે તમારા ટૅબ્લેટ પર પ્રયાસ કરો."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"આ ઍપ દ્વારા વધારાની સુરક્ષાની વિનંતી કરવામાં આવી રહી છે. તેના બદલે તમારા ફોન પર પ્રયાસ કરો."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"આ ઍપ Androidના જૂના વર્ઝન માટે બનાવવામાં આવ્યું હતું અને તે કદાચ તે યોગ્ય રીતે કાર્ય કરી શકશે નહીં. અપડેટ માટે તપાસવાનો પ્રયાસ કરો અથવા ડેવલપરનો સંપર્ક કરો."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"અપડેટ માટે તપાસો"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"તમારી પાસે નવા સંદેશા છે"</string> @@ -2293,9 +2278,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g>નો અનુવાદ કર્યો."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"<xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>થી <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>માં સંદેશનો અનુવાદ કરવામાં આવ્યો."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"બૅકગ્રાઉન્ડ પ્રવૃત્તિ"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"કોઈ ઍપ બૅટરીનો વપરાશ કરી રહી છે"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"કોઈ ઍપ બૅટરીનો ઝડપથી વપરાશ કરી રહી છે"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"કોઈ ઍપ હજી પણ સક્રિય છે"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> દ્વારા બૅકગ્રાઉન્ડમાં બૅટરીનો વપરાશ કરવામાં આવી રહ્યો છે. રિવ્યૂ કરવા માટે ટૅપ કરો."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> બૅકગ્રાઉન્ડમાં ચાલી રહી છે. બૅટરીનો વપરાશ મેનેજ કરવા માટે ટૅપ કરો."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g>, બૅટરીની આવરદાને અસર કરી શકે છે. બધી સક્રિય ઍપનો રિવ્યૂ કરવા માટે ટૅપ કરો."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"સક્રિય ઍપ ચેક કરો"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"તમારા <xliff:g id="DEVICE">%1$s</xliff:g> પરથી ફોનના કૅમેરાનો ઍક્સેસ કરી શકતાં નથી"</string> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index a88cf0379902..bef53d6afd3d 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> इस समय उपलब्ध नहीं है."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> उपलब्ध नहीं है"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"अनुमति ज़रूरी है"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"कैमरा उपलब्ध नहीं है"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"फ़ोन पर जारी रखें"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"माइक्रोफ़ोन उपलब्ध नहीं है"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV की सेटिंग उपलब्ध नहीं हैं"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"टैबलेट की सेटिंग उपलब्ध नहीं हैं"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"फ़ोन की सेटिंग उपलब्ध नहीं हैं"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"आपके <xliff:g id="DEVICE">%1$s</xliff:g> पर इसे ऐक्सेस नहीं किया जा सकता. इसके बजाय, अपने Android TV डिवाइस पर ऐक्सेस करने की कोशिश करें."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"आपके <xliff:g id="DEVICE">%1$s</xliff:g> पर इसे ऐक्सेस नहीं किया जा सकता. इसके बजाय, अपने टैबलेट पर ऐक्सेस करने की कोशिश करें."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"आपके <xliff:g id="DEVICE">%1$s</xliff:g> पर इसे ऐक्सेस नहीं किया जा सकता. इसके बजाय, अपने फ़ोन पर ऐक्सेस करने की कोशिश करें."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"इस समय, आपके <xliff:g id="DEVICE">%1$s</xliff:g> पर इसे ऐक्सेस नहीं किया जा सकता. इसके बजाय, अपने Android TV डिवाइस पर ऐक्सेस करने की कोशिश करें."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"इस समय, आपके <xliff:g id="DEVICE">%1$s</xliff:g> पर इसे ऐक्सेस नहीं किया जा सकता. इसके बजाय, अपने टैबलेट पर ऐक्सेस करने की कोशिश करें."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"इस समय, आपके <xliff:g id="DEVICE">%1$s</xliff:g> पर इसे ऐक्सेस नहीं किया जा सकता. इसके बजाय, अपने फ़ोन पर ऐक्सेस करने की कोशिश करें."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"यह ऐप्लिकेशन ज़्यादा सुरक्षा का अनुरोध कर रहा है. इसके बजाय, अपने Android TV डिवाइस पर ऐक्सेस करने की कोशिश करें."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"यह ऐप्लिकेशन ज़्यादा सुरक्षा का अनुरोध कर रहा है. इसके बजाय, अपने टैबलेट पर ऐक्सेस करने की कोशिश करें."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"यह ऐप्लिकेशन ज़्यादा सुरक्षा का अनुरोध कर रहा है. इसके बजाय, अपने फ़ोन पर ऐक्सेस करने की कोशिश करें."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"यह ऐप्लिकेशन Android के पुराने वर्शन के लिए बनाया गया था, इसलिए हो सकता है कि यह सही से काम न करे. देखें कि अपडेट मौजूद हैं या नहीं, या फिर डेवलपर से संपर्क करें."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"देखें कि अपडेट मौजूद है या नहीं"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"आपके पास नए संदेश हैं"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"ज़्यादा जानने और बदलाव करने के लिए टैप करें."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"परेशान न करें की सुविधा बदल गई है"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"टैप करके देखें कि किन चीज़ों पर रोक लगाई गई है."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"सूचना सेटिंग देखें"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13 में जो ऐप्लिकेशन इंस्टॉल किए जाएंगे, उन्हें आपको सूचनाएं भेजने के लिए अनुमति लेनी होगी. पहले से इंस्टॉल किए गए ऐप्लिकेशन को दी गई अनुमति बदलने के लिए टैप करें."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"बाद में याद दिलाएं"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"बंद करें"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"सिस्टम"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"सेटिंग"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"कैमरा"</string> @@ -2090,7 +2071,7 @@ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"चालू करें"</string> <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"बंद करें"</string> <string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"ज़्यादा जानें"</string> - <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Android 12 में, ज़रूरत के हिसाब से सूचनाएं पाने की सुविधा की जगह अब \'बेहतर सूचनाएं\' सुविधा काम करेगी. यह सुविधा आपको कार्रवाइयों और जवाबों के सुझाव दिखाती है. साथ ही, आपके डिवाइस पर मिलने वाली सूचनाओं को व्यवस्थित करती है.\n\n\'बेहतर सूचनाएं\' सुविधा, डिवाइस पर मिलने वाली सभी सूचनाओं का कॉन्टेंट ऐक्सेस कर सकती है. इसमें आपकी निजी जानकारी, जैसे कि संपर्कों के नाम और मैसेज शामिल हैं. यह सुविधा, सूचनाओं को खारिज कर सकती है या उनका जवाब भी दे सकती है, जैसे कि फ़ोन कॉल का जवाब देना और \'परेशान न करें\' को कंट्रोल करना."</string> + <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Android 12 में, ज़रूरत के हिसाब से सूचनाएं पाने की सुविधा की जगह अब \'बेहतर सूचनाएं\' सुविधा काम करेगी. यह सुविधा आपको कार्रवाइयों और जवाबों के सुझाव दिखाती है. साथ ही, आपके डिवाइस पर मिलने वाली सूचनाओं को व्यवस्थित करती है.\n\n\'बेहतर सूचनाएं\' सुविधा, डिवाइस पर मिलने वाली सूचनाओं का कॉन्टेंट ऐक्सेस कर सकती है. इसमें आपकी निजी जानकारी, जैसे कि संपर्कों के नाम और मैसेज शामिल हैं. यह सुविधा, सूचनाओं को खारिज कर सकती है या उनका जवाब भी दे सकती है, जैसे कि फ़ोन कॉल का जवाब देना और \'परेशान न करें\' को कंट्रोल करना."</string> <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"रूटीन मोड जानकारी की सूचना"</string> <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"बैटरी आम तौर पर जितने समय चलती है, उससे पहले खत्म हो सकती है"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"बैटरी लाइफ़ बढ़ाने के लिए \'बैटरी सेवर\' चालू हो गया है"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> का अनुवाद किया गया."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"मैसेज का <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> से <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> में अनुवाद किया गया."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"बैकग्राउंड में हो रही गतिविधि"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"कोई ऐप्लिकेशन, बैटरी का इस्तेमाल कर रहा है"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"कोई ऐप्लिकेशन अब भी चालू है"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g>, बैकग्राउंड में बैटरी का इस्तेमाल कर रहा है. समीक्षा करने के लिए टैप करें."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> से, आपके डिवाइस की बैटरी लाइफ़ पर असर पड़ सकता है. चालू ऐप्लिकेशन देखने के लिए टैप करें."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"चालू ऐप्लिकेशन देखें"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"आपके <xliff:g id="DEVICE">%1$s</xliff:g> से फ़ोन के कैमरे को ऐक्सेस नहीं किया जा सकता"</string> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index cedb91517d58..21bcd20a27f9 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -1934,36 +1934,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutačno nije dostupna."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> – nije dostupno"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Potrebno je dopuštenje"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kamera nije dostupna"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Nastavite na telefonu"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofon nije dostupan"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Postavke Android TV-a nisu dostupne"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Postavke tableta nisu dostupne"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Postavke telefona nisu dostupne"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Toj aplikaciji nije moguće pristupiti na vašem uređaju <xliff:g id="DEVICE">%1$s</xliff:g>. Pokušajte joj pristupiti na Android TV uređaju."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Toj aplikaciji nije moguće pristupiti na vašem uređaju <xliff:g id="DEVICE">%1$s</xliff:g>. Pokušajte joj pristupiti na tabletu."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Toj aplikaciji nije moguće pristupiti na vašem uređaju <xliff:g id="DEVICE">%1$s</xliff:g>. Pokušajte joj pristupiti na telefonu."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Trenutačno toj aplikaciji nije moguće pristupiti na vašem uređaju <xliff:g id="DEVICE">%1$s</xliff:g>. Pokušajte joj pristupiti na Android TV uređaju."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Trenutačno toj aplikaciji nije moguće pristupiti na vašem uređaju <xliff:g id="DEVICE">%1$s</xliff:g>. Pokušajte joj pristupiti na tabletu."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Trenutačno toj aplikaciji nije moguće pristupiti na vašem uređaju <xliff:g id="DEVICE">%1$s</xliff:g>. Pokušajte joj pristupiti na telefonu."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Ta aplikacija zahtijeva dodatnu sigurnost. Pokušajte joj pristupiti na Android TV uređaju."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Ta aplikacija zahtijeva dodatnu sigurnost. Pokušajte joj pristupiti na tabletu."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Ta aplikacija zahtijeva dodatnu sigurnost. Pokušajte joj pristupiti na telefonu."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ova je aplikacija razvijena za stariju verziju Androida i možda neće funkcionirati pravilno. Potražite ažuriranja ili se obratite razvojnom programeru."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Provjeri ažuriranja"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Imate nove poruke"</string> @@ -2068,14 +2053,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Dodirnite da biste saznali više i promijenili postavke."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Promijenjena je postavka Ne uznemiravaj"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Dodirnite da biste provjerili što je blokirano."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Pregledajte postavke obavijesti"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"U Androidu 13 aplikacije koje instalirate trebaju vaše dopuštenje za slanje obavijesti. Dodirnite da biste promijenili to dopuštenje za postojeće aplikacije."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Podsjeti me kasnije"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Odbaci"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Sustav"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Postavke"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Fotoaparat"</string> @@ -2091,7 +2072,7 @@ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"U redu"</string> <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Isključi"</string> <string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Saznajte više"</string> - <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"U Androidu 12 poboljšane obavijesti zamjenjuju prilagodljive obavijesti za Android. Ta značajka prikazuje predložene radnje i odgovore te organizira vaše obavijesti.\n\nPoboljšane obavijesti mogu pristupiti sadržaju obavijesti, uključujući osobne podatke kao što su imena kontakata i poruke. Ta značajka može i odbacivati obavijesti ili poduzimati radnje u vezi s njima, na primjer može odgovarati na telefonske pozive i upravljati značajkom Ne uznemiravaj."</string> + <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"U Androidu 12 poboljšane obavijesti zamjenjuju prilagodljive obavijesti za Android. Ta značajka prikazuje predložene radnje i odgovore te organizira vaše obavijesti.\n\nPoboljšane obavijesti mogu pristupati sadržaju obavijesti, uključujući osobne podatke kao što su imena kontakata i poruke. Ta značajka može i odbacivati obavijesti ili poduzimati radnje u vezi s njima, na primjer može odgovarati na telefonske pozive i upravljati značajkom Ne uznemiravaj."</string> <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Obavještavanje o informacijama u Rutinskom načinu rada"</string> <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Baterija se može isprazniti prije uobičajenog vremena punjenja"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Štednja baterije aktivirana je kako bi se produljilo trajanje baterije"</string> @@ -2294,9 +2275,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Preveden je tekst <xliff:g id="MESSAGE">%1$s</xliff:g>."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Poruka je prevedena: <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> na <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Aktivnost u pozadini"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Aplikacija koristi bateriju"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Aplikacija prazni bateriju"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Aplikacija je i dalje aktivna"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> koristi bateriju u pozadini. Dodirnite za pregled."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> se pokreće u pozadini. Dodirnite da biste upravljali potrošnjom baterije."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> može utjecati na trajanje baterije. Dodirnite da biste pregledali aktivne aplikacije."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Provjera aktivnih aplikacija"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"S vašeg uređaja <xliff:g id="DEVICE">%1$s</xliff:g> nije moguće pristupiti fotoaparatu telefona"</string> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index ba3c66c8387f..21c40ade7637 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> jelenleg nem hozzáférhető."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"A(z) <xliff:g id="ACTIVITY">%1$s</xliff:g> nem áll rendelkezése"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Engedély szükséges"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"A kamera nem áll rendelkezésre"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Folytatás a telefonon"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"A mikrofon nem áll rendelkezésre"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Az Android TV beállításai nem állnak rendelkezésre"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"A táblagép beállításai nem állnak rendelkezésre"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"A telefon beállításai nem állnak rendelkezésre"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Ehhez nem lehet hozzáférni a következő eszközön: <xliff:g id="DEVICE">%1$s</xliff:g>. Próbálja újra Android TV-eszközén."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Ehhez nem lehet hozzáférni a következő eszközön: <xliff:g id="DEVICE">%1$s</xliff:g>. Próbálja újra a táblagépén."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Ehhez nem lehet hozzáférni a következő eszközön: <xliff:g id="DEVICE">%1$s</xliff:g>. Próbálja újra a telefonján."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Ehhez jelenleg nem lehet hozzáférni a következő eszközön: <xliff:g id="DEVICE">%1$s</xliff:g>. Próbálja újra Android TV-eszközén."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Ehhez jelenleg nem lehet hozzáférni a következő eszközön: <xliff:g id="DEVICE">%1$s</xliff:g>. Próbálja újra a táblagépén."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Ehhez jelenleg nem lehet hozzáférni a következő eszközön: <xliff:g id="DEVICE">%1$s</xliff:g>. Próbálja újra a telefonján."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Ez az alkalmazás nagyobb biztonságot igényel. Próbálja újra Android TV-eszközén."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Ez az alkalmazás nagyobb biztonságot igényel. Próbálja újra a táblagépén."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Ez az alkalmazás nagyobb biztonságot igényel. Próbálja újra a telefonján."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ez az alkalmazás az Android egyik korábbi verziójához készült, így elképzelhető, hogy nem működik majd megfelelően ezen a rendszeren. Keressen frissítéseket, vagy vegye fel a kapcsolatot a fejlesztővel."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Frissítés keresése"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Új üzenetei érkeztek"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Koppintással további információhoz juthat, és elvégezheti a módosítást."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Módosultak a Ne zavarjanak mód beállításai"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Koppintson a letiltott elemek megtekintéséhez."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Értesítési beállítások áttekintése"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13-as rendszeren a telepített alkalmazásoknak engedélyre van szükségük értesítések küldéséhez. Koppintással módosíthatja ezt az engedélyt a meglévő alkalmazások esetében."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Emlékeztessen később"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Bezárás"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Rendszer"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Beállítások"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Kamera"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"A következő lefordítása sikeresen megtörtént: <xliff:g id="MESSAGE">%1$s</xliff:g>."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Sikerült lefordítani az üzenetet <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> nyelvről <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> nyelvre."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Háttértevékenység"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Az egyik alkalmazás használja az akkumulátort"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Egy alkalmazás meríti az akkumulátort"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Az egyik alkalmazás még aktív"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"A(z) <xliff:g id="APP">%1$s</xliff:g> a háttérben használja az akkumulátort. Koppintson az áttekintéshez."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"A(z) <xliff:g id="APP">%1$s</xliff:g> fut a háttérben. Koppintson az akkumulátorhasználat kezeléséhez."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"A(z) <xliff:g id="APP">%1$s</xliff:g> befolyásolhatja az akkumulátor üzemidejét. Koppintson az aktív alkalmazások áttekintéséhez."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Aktív alkalmazások ellenőrzése"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Nem lehet hozzáférni a telefon kamerájához a következő eszközön: <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml index 395c78b3bf19..7c966b364d5b 100644 --- a/core/res/res/values-hy/strings.xml +++ b/core/res/res/values-hy/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածն այս պահին հասանելի չէ։"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g>՝ անհասանելի է"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Անհրաժեշտ է թույլտվություն"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Տեսախցիկն անհասանելի է"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Շարունակեք հեռախոսով"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Խոսափողն անհասանելի է"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV-ի կարգավորումներն անհասանելի են"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Պլանշետի կարգավորումներն անհասանելի են"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Հեռախոսի կարգավորումներն անհասանելի են"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Հնարավոր չէ բացել հավելվածը ձեր <xliff:g id="DEVICE">%1$s</xliff:g> սարքում։ Օգտագործեք ձեր Android TV սարքը։"</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Հնարավոր չէ բացել հավելվածը ձեր <xliff:g id="DEVICE">%1$s</xliff:g> սարքում։ Օգտագործեք ձեր պլանշետը։"</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Հնարավոր չէ բացել հավելվածը ձեր <xliff:g id="DEVICE">%1$s</xliff:g> սարքում։ Օգտագործեք ձեր հեռախոսը։"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Այս պահին հնարավոր չէ բացել հավելվածը <xliff:g id="DEVICE">%1$s</xliff:g> սարքում։ Օգտագործեք ձեր Android TV սարքը։"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Այս պահին հնարավոր չէ բացել հավելվածը <xliff:g id="DEVICE">%1$s</xliff:g> սարքում։ Օգտագործեք ձեր պլանշետը։"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Այս պահին հնարավոր չէ բացել հավելվածը <xliff:g id="DEVICE">%1$s</xliff:g> սարքում։ Օգտագործեք ձեր հեռախոսը։"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Այս հավելվածը պահանջում է անվտանգության լրացուցիչ միջոցներ։ Օգտագործեք ձեր Android TV սարքը։"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Այս հավելվածը պահանջում է անվտանգության լրացուցիչ միջոցներ։ Օգտագործեք ձեր պլանշետը։"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Այս հավելվածը պահանջում է անվտանգության լրացուցիչ միջոցներ։ Օգտագործեք ձեր հեռախոսը։"</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Այս հավելվածը ստեղծվել է Android-ի ավելի հին տարբերակի համար և կարող է պատշաճ չաշխատել: Ստուգեք թարմացումների առկայությունը կամ դիմեք մշակողին:"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Ստուգել նոր տարբերակի առկայությունը"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Դուք ունեք նոր հաղորդագրություններ"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Հպեք՝ ավելին իմանալու և կարգավորումները փոխելու համար:"</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"«Չանհանգստացնել» ռեժիմի կարգավորումները փոխվել են"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Հպեք՝ տեսնելու, թե ինչ է արգելափակվել:"</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Ստուգեք ծանուցումների կարգավորումները"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13-ում ձեր տեղադրած հավելվածներին անհրաժեշտ է տրամադրել ծանուցումներ ուղարկելու թույլտվություն։ Հպեք և փոխեք այս թույլտվությունն արդեն տեղադրված հավելվածների համար։"</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Հիշեցնել ավելի ուշ"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Փակել"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Համակարգ"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Կարգավորումներ"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Տեսախցիկ"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"«<xliff:g id="MESSAGE">%1$s</xliff:g>» հաղորդագրությունը թարգմանված է։"</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Հաղորդագրությունը <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>ից թարգմանվել է <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>։"</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Ակտիվ հավելվածներ ֆոնային ռեժիմում"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Հավելվածն օգտագործում է մարտկոցի լիցքը"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Հավելվածներից մեկն արագ սպառում է մարտկոցի լիցքը"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Հավելվածը դեռ ակտիվ է"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> հավելվածն օգտագործում է մարտկոցի լիցքը ֆոնային ռեժիմում։ Հպեք՝ մանրամասները տեսնելու համար։"</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> հավելվածն աշխատում է ֆոնային ռեժիմում։ Հպեք՝ մարտկոցի օգտագործումը կառավարելու համար։"</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> հավելվածը կարող է ազդել մարտկոցի աշխատաժամանակի վրա։ Հպեք՝ ակտիվ հավելվածները տեսնելու համար։"</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Ստուգել ակտիվ հավելվածները"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Հնարավոր չէ օգտագործել հեռախոսի տեսախցիկը ձեր <xliff:g id="DEVICE">%1$s</xliff:g> սարքից"</string> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 3ab226365816..61104d3a6ab6 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -1014,7 +1014,7 @@ <string name="js_dialog_before_unload" msgid="7213364985774778744">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nYakin ingin beranjak dari halaman ini?"</string> <string name="save_password_label" msgid="9161712335355510035">"Konfirmasi"</string> <string name="double_tap_toast" msgid="7065519579174882778">"Kiat: Ketuk dua kali untuk memperbesar dan memperkecil."</string> - <string name="autofill_this_form" msgid="3187132440451621492">"IsiOtomatis"</string> + <string name="autofill_this_form" msgid="3187132440451621492">"Isi Otomatis"</string> <string name="setup_autofill" msgid="5431369130866618567">"Siapkan Pengisian Otomatis"</string> <string name="autofill_window_title" msgid="4379134104008111961">"IsiOtomatis dengan <xliff:g id="SERVICENAME">%1$s</xliff:g>"</string> <string name="autofill_address_name_separator" msgid="8190155636149596125">" "</string> @@ -1137,7 +1137,7 @@ <string name="selectTextMode" msgid="3225108910999318778">"Pilih teks"</string> <string name="undo" msgid="3175318090002654673">"Urungkan"</string> <string name="redo" msgid="7231448494008532233">"Ulangi"</string> - <string name="autofill" msgid="511224882647795296">"IsiOtomatis"</string> + <string name="autofill" msgid="511224882647795296">"Isi Otomatis"</string> <string name="textSelectionCABTitle" msgid="5151441579532476940">"Pemilihan teks"</string> <string name="addToDictionary" msgid="8041821113480950096">"Tambahkan ke kamus"</string> <string name="deleteText" msgid="4200807474529938112">"Hapus"</string> @@ -1679,11 +1679,11 @@ <string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"AKTIF"</string> <string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"NONAKTIF"</string> <string name="accessibility_enable_service_title" msgid="3931558336268541484">"Izinkan <xliff:g id="SERVICE">%1$s</xliff:g> memiliki kontrol penuh atas perangkat Anda?"</string> - <string name="accessibility_service_warning_description" msgid="291674995220940133">"Kontrol penuh sesuai untuk aplikasi yang membantu Anda terkait kebutuhan aksesibilitas, tetapi tidak untuk sebagian besar aplikasi."</string> + <string name="accessibility_service_warning_description" msgid="291674995220940133">"Kontrol penuh sesuai untuk aplikasi yang mendukung kebutuhan aksesibilitas Anda, tetapi tidak untuk sebagian besar aplikasi."</string> <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"Melihat dan mengontrol layar"</string> - <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Aplikasi dapat membaca semua konten di layar dan menampilkan konten di atas aplikasi lain."</string> + <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"Voice Access dapat membaca semua konten di layar dan menampilkan konten di atas aplikasi lain."</string> <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"Menampilkan dan melakukan tindakan"</string> - <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Aplikasi dapat melacak interaksi Anda dengan aplikasi atau sensor hardware, dan melakukan interaksi dengan aplikasi untuk Anda."</string> + <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"Voice Access dapat melacak interaksi Anda dengan aplikasi atau sensor hardware, dan berinteraksi dengan aplikasi untuk Anda."</string> <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"Izinkan"</string> <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Tolak"</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Ketuk fitur untuk mulai menggunakannya:"</string> @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak tersedia saat ini."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> tidak tersedia"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Perlu izin"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kamera tidak tersedia"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Lanjutkan di ponsel"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofon tidak tersedia"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Setelan Android TV tidak tersedia"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Setelan tablet tidak tersedia"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Setelan ponsel tidak tersedia"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Aplikasi ini tidak dapat diakses di <xliff:g id="DEVICE">%1$s</xliff:g>. Coba di perangkat Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Aplikasi ini tidak dapat diakses di <xliff:g id="DEVICE">%1$s</xliff:g>. Coba di tablet."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Aplikasi ini tidak dapat diakses di <xliff:g id="DEVICE">%1$s</xliff:g>. Coba di ponsel."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Aplikasi ini tidak dapat diakses di <xliff:g id="DEVICE">%1$s</xliff:g> untuk saat ini. Coba di perangkat Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Aplikasi ini tidak dapat diakses di <xliff:g id="DEVICE">%1$s</xliff:g> untuk saat ini. Coba di tablet."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Aplikasi ini tidak dapat diakses di <xliff:g id="DEVICE">%1$s</xliff:g> untuk saat ini. Coba di ponsel."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Aplikasi ini meminta keamanan tambahan. Coba di perangkat Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Aplikasi ini meminta keamanan tambahan. Coba di tablet."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Aplikasi ini meminta keamanan tambahan. Coba di ponsel."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Aplikasi ini dibuat untuk Android versi lama dan mungkin tidak berfungsi sebagaimana mestinya. Coba periksa apakah ada update, atau hubungi developer."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Periksa apakah ada update"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Ada pesan baru"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Ketuk untuk mempelajari lebih lanjut dan mengubah."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Jangan Ganggu telah berubah"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Ketuk untuk memeriksa item yang diblokir."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Tinjau setelan notifikasi"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Di Android 13, aplikasi yang Anda instal memerlukan izin untuk mengirim notifikasi. Ketuk guna mengubah izin ini untuk aplikasi yang sudah ada."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Ingatkan saya nanti"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Tutup"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Sistem"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Setelan"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Kamera"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> Diterjemahkan."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Pesan diterjemahkan dari bahasa <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> ke <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Aktivitas Latar Belakang"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Aplikasi sedang menggunakan daya baterai"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Aplikasi masih aktif"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> sedang menggunakan daya baterai di latar belakang. Ketuk untuk meninjau."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> mungkin memengaruhi masa pakai baterai. Ketuk untuk meninjau aplikasi aktif."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Periksa aplikasi aktif"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Tidak dapat mengakses kamera ponsel dari <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml index 60b571d04954..8b8a22883db6 100644 --- a/core/res/res/values-is/strings.xml +++ b/core/res/res/values-is/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> er ekki tiltækt núna."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ekki í boði"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Heimildar krafist"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Myndavél ekki tiltæk"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Halda áfram í símanum"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Hljóðnemi ekki tiltækur"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV stillingar ekki tiltækar"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Spjaldtölvustillingar ekki tiltækar"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Símastillingar ekki tiltækar"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Ekki er hægt að opna þetta í <xliff:g id="DEVICE">%1$s</xliff:g>. Prófaðu það í Android TV tækinu í staðinn."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Ekki er hægt að opna þetta í <xliff:g id="DEVICE">%1$s</xliff:g>. Prófaðu það í spjaldtölvunni í staðinn."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Ekki er hægt að opna þetta í <xliff:g id="DEVICE">%1$s</xliff:g>. Prófaðu það í símanum í staðinn."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Aðgangur að þessu í <xliff:g id="DEVICE">%1$s</xliff:g> er ekki í boði eins og er. Prófaðu það í Android TV tækinu í staðinn."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Aðgangur að þessu í <xliff:g id="DEVICE">%1$s</xliff:g> er ekki í boði eins og er. Prófaðu það í spjaldtölvunni í staðinn."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Aðgangur að þessu í <xliff:g id="DEVICE">%1$s</xliff:g> er ekki í boði eins og er. Prófaðu það í símanum í staðinn."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Þetta forrit biður um viðbótaröryggi. Prófaðu það í Android TV tækinu í staðinn."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Þetta forrit biður um viðbótaröryggi. Prófaðu það í spjaldtölvunni í staðinn."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Þetta forrit biður um viðbótaröryggi. Prófaðu það í símanum í staðinn."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Þetta forrit var hannað fyrir eldri útgáfu af Android og ekki er víst að það virki eðlilega. Athugaðu hvort uppfærslur séu í boði eða hafðu samband við þróunaraðilann."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Leita að uppfærslu"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Þú ert með ný skilaboð"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Ýttu til að fá frekari upplýsingar og breyta."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"„Ónáðið ekki“ var breytt"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Ýttu til að skoða hvað lokað hefur verið á."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Yfirfara tilkynningastillingar"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Í Android 13 þurfa forrit sem þú setur upp heimild frá þér til að senda tilkynningar. Ýttu til að breyta þessari heimild fyrir forrit sem fyrir eru."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Minna mig á seinna"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Hunsa"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Kerfi"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Stillingar"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Myndavél"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> var þýtt."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Skilaboð þýdd úr <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> á <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Bakgrunnsvirkni"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Forrit notar rafhlöðuorku"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Forrit er enn virkt"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> notar rafhlöðuorku í bakgrunni. Ýttu til að skoða."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> gæti haft áhrif á rafhlöðuendingu. Ýttu til að skoða virk forrit."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Skoða virk forrit"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Ekki er hægt að opna myndavél símans úr <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index f1771aa94310..bf591eca6d6c 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -1851,7 +1851,7 @@ <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string> <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"Il risparmio energetico attiva il tema scuro e limita o disattiva l\'attività in background, nonché alcuni effetti visivi, funzionalità e connessioni di rete."</string> <string name="battery_saver_description" msgid="8518809702138617167">"Il risparmio energetico attiva il tema scuro e limita o disattiva l\'attività in background, nonché alcuni effetti visivi, funzionalità e connessioni di rete."</string> - <string name="data_saver_description" msgid="4995164271550590517">"Per contribuire a ridurre l\'utilizzo dei dati, la funzione Risparmio dati impedisce ad alcune app di inviare o ricevere dati in background. Un\'app in uso può accedere ai dati, ma potrebbe farlo con meno frequenza. Esempio: le immagini non vengono visualizzate finché non le tocchi."</string> + <string name="data_saver_description" msgid="4995164271550590517">"Per contribuire a ridurre l\'utilizzo dei dati, la funzionalità Risparmio dati impedisce ad alcune app di inviare o ricevere dati in background. Un\'app in uso può accedere ai dati, ma potrebbe farlo con meno frequenza. Per esempio, è possibile che le immagini non vengano visualizzate finché non le tocchi."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Attivare Risparmio dati?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Attiva"</string> <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Per un minuto (fino alle ore {formattedTime})}other{Per # minuti (fino alle ore {formattedTime})}}"</string> @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"L\'app <xliff:g id="APP_NAME">%1$s</xliff:g> non è al momento disponibile."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> non disponibile"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"È necessaria l\'autorizzazione"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Fotocamera non disponibile"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Continua sul telefono"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Microfono non disponibile"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Impostazioni di Android TV non disponibili"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Impostazioni del tablet non disponibili"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Impostazioni del telefono non disponibili"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Non è possibile accedere a questa app su <xliff:g id="DEVICE">%1$s</xliff:g>. Prova a usare il dispositivo Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Non è possibile accedere a questa app su <xliff:g id="DEVICE">%1$s</xliff:g>. Prova a usare il tablet."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Non è possibile accedere a questa app su <xliff:g id="DEVICE">%1$s</xliff:g>. Prova a usare il telefono."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Al momento non è possibile accedere a questa app su <xliff:g id="DEVICE">%1$s</xliff:g>. Prova a usare il dispositivo Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Al momento non è possibile accedere a questa app su <xliff:g id="DEVICE">%1$s</xliff:g>. Prova a usare il tablet."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Al momento non è possibile accedere a questa app su <xliff:g id="DEVICE">%1$s</xliff:g>. Prova a usare il telefono."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Questa app richiede maggiore sicurezza. Prova a usare il dispositivo Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Questa app richiede maggiore sicurezza. Prova a usare il tablet."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Questa app richiede maggiore sicurezza. Prova a usare il telefono."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Questa app è stata realizzata per una versione precedente di Android e potrebbe non funzionare correttamente. Prova a verificare la disponibilità di aggiornamenti o contatta lo sviluppatore."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Cerca aggiornamenti"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Hai nuovi messaggi"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Tocca per avere ulteriori informazioni e modificare."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"L\'impostazione Non disturbare è cambiata"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Tocca per controllare le notifiche bloccate."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Controlla le impostazioni di notifica"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"In Android 13, le app che installi devono avere la tua autorizzazione per poter inviare notifiche. Tocca per cambiare questa autorizzazione per le app esistenti."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Ricordamelo dopo"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Ignora"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Sistema"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Impostazioni"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Fotocamera"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Messaggio <xliff:g id="MESSAGE">%1$s</xliff:g> tradotto."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Messaggio tradotto dalla lingua <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> alla lingua <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Attività in background"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Un\'app sta usando la batteria"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"C\'è un\'app ancora attiva"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> sta usando la batteria in background. Tocca per controllare."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> potrebbe influire sulla durata della batteria. Tocca per controllare le app attive."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Verifica le app attive"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Impossibile accedere alla fotocamera del telefono dal tuo <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 44e6658969f6..e1c696f4dca6 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -1935,36 +1935,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> לא זמינה בשלב זה."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> לא זמינה"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"דרושה הרשאה"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"המצלמה לא זמינה"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"יש להמשיך בטלפון"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"המיקרופון לא זמין"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"ההגדרות של Android TV לא זמינות"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"ההגדרות של הטאבלט לא זמינות"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"ההגדרות של הטלפון לא זמינות"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"אי אפשר לגשת לאפליקציה הזו במכשיר <xliff:g id="DEVICE">%1$s</xliff:g>. במקום זאת, יש לנסות במכשיר Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"אי אפשר לגשת לאפליקציה הזו במכשיר <xliff:g id="DEVICE">%1$s</xliff:g>. במקום זאת, יש לנסות בטאבלט."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"אי אפשר לגשת לאפליקציה הזו במכשיר <xliff:g id="DEVICE">%1$s</xliff:g>. במקום זאת, יש לנסות בטלפון."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"אי אפשר לגשת לאפליקציה הזו במכשיר <xliff:g id="DEVICE">%1$s</xliff:g> כרגע. במקום זאת, יש לנסות במכשיר Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"אי אפשר לגשת לאפליקציה הזו במכשיר <xliff:g id="DEVICE">%1$s</xliff:g> כרגע. במקום זאת, יש לנסות בטאבלט."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"אי אפשר לגשת לאפליקציה הזו במכשיר <xliff:g id="DEVICE">%1$s</xliff:g> כרגע. במקום זאת, יש לנסות בטלפון."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"האפליקציה הזו מבקשת אמצעי אבטחה נוסף. במקום זאת, יש לנסות במכשיר Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"האפליקציה הזו מבקשת אמצעי אבטחה נוסף. במקום זאת, יש לנסות בטאבלט."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"האפליקציה הזו מבקשת אמצעי אבטחה נוסף. במקום זאת, יש לנסות בטלפון."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"האפליקציה הזו עוצבה לגרסה ישנה יותר של Android וייתכן שלא תפעל כראוי. ניתן לבדוק אם יש עדכונים או ליצור קשר עם המפתח."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"יש עדכון חדש?"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"יש לך הודעות חדשות"</string> @@ -2069,14 +2054,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"אפשר להקיש כדי לקבל מידע נוסף ולבצע שינויים."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"ההגדרה \'נא לא להפריע\' השתנתה"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"יש להקיש כדי לבדוק מה חסום."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"בדיקת הגדרת ההתראות"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"ב-Android 13, עליך לתת לאפליקציות שהתקנת הרשאה לשלוח התראות. אפשר להקיש כדי לשנות את ההרשאה הזו באפליקציות קיימות."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"תזכירו לי מאוחר יותר"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"סגירה"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"מערכת"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"הגדרות"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"מצלמה"</string> @@ -2295,9 +2276,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"ההודעה <xliff:g id="MESSAGE">%1$s</xliff:g> תורגמה."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"ההודעה תורגמה מ<xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> ל<xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"פעילות ברקע"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"אפליקציה כלשהי צורכת סוללה"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"אחת האפליקציות מרוקנת את הסוללה"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"אפליקציה כלשהי עדיין פעילה"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"האפליקציה <xliff:g id="APP">%1$s</xliff:g> צורכת סוללה ברקע. אפשר להקיש כדי לבדוק."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> פועלת ברקע. יש להקיש כדי לנהל את השימוש בסוללה."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"האפליקציה <xliff:g id="APP">%1$s</xliff:g> עלולה להשפיע על חיי הסוללה. אפשר להקיש כדי לבדוק את האפליקציות הפעילות."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"כדאי לבדוק את האפליקציות הפעילות"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"לא ניתן לגשת למצלמה של הטלפון מה‑<xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index c3b84bf09e6b..dff29f980e4b 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"現在 <xliff:g id="APP_NAME">%1$s</xliff:g> はご利用になれません。"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g>は利用できません"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"権限が必要"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"カメラ: 使用不可"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"スマートフォンで続行"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"マイク: 使用不可"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV の設定: 使用不可"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"タブレットの設定: 使用不可"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"スマートフォンの設定: 使用不可"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"<xliff:g id="DEVICE">%1$s</xliff:g> からはアクセスできません。Android TV デバイスでのアクセスをお試しください。"</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"<xliff:g id="DEVICE">%1$s</xliff:g> からはアクセスできません。タブレットでのアクセスをお試しください。"</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"<xliff:g id="DEVICE">%1$s</xliff:g> からはアクセスできません。スマートフォンでのアクセスをお試しください。"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"現在、<xliff:g id="DEVICE">%1$s</xliff:g> からアクセスできません。Android TV デバイスでのアクセスをお試しください。"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"現在、<xliff:g id="DEVICE">%1$s</xliff:g> からアクセスできません。タブレットでのアクセスをお試しください。"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"現在、<xliff:g id="DEVICE">%1$s</xliff:g> からアクセスできません。スマートフォンでのアクセスをお試しください。"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"このアプリはセキュリティの強化を求めています。Android TV デバイスでのアクセスをお試しください。"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"このアプリはセキュリティの強化を求めています。タブレットでのアクセスをお試しください。"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"このアプリはセキュリティの強化を求めています。スマートフォンでのアクセスをお試しください。"</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"このアプリは以前のバージョンの Android 用に作成されており、正常に動作しない可能性があります。アップデートを確認するか、デベロッパーにお問い合わせください。"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"アップデートを確認"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"新着メッセージがあります"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"タップすると、詳細を確認して設定を変更できます。"</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"サイレント モードが変わりました"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"タップしてブロック対象をご確認ください。"</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"通知設定の確認"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13 では、インストールするアプリに、通知を送信する権限を付与する必要があります。既存のアプリのこの権限を変更するには、タップしてください。"</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"後で"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"閉じる"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"システム"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"設定"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"カメラ"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> に翻訳しました。"</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"メッセージを<xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>から<xliff:g id="TO_LANGUAGE">%2$s</xliff:g>に翻訳しました。"</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"バックグラウンド アクティビティ"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"アプリがバッテリーを使用しています"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"アプリがバッテリーを消費しています"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"アプリがまだアクティブです"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> がバックグラウンドでバッテリーを使用しています。タップしてご確認ください。"</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> がバックグラウンドで実行されています。タップすると、バッテリー使用量を管理できます。"</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> がバッテリー駆動時間に影響を与えている可能性があります。タップして、実行中のアプリをご確認ください。"</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"実行中のアプリをチェック"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"<xliff:g id="DEVICE">%1$s</xliff:g> からスマートフォンのカメラにアクセスできません"</string> diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml index 82e02f83c3af..e98240e45949 100644 --- a/core/res/res/values-ka/strings.xml +++ b/core/res/res/values-ka/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ამჟამად მიუწვდომელია."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> მიუწვდომელია"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"საჭიროა ნებართვა"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"კამერა მიუწვდომელია"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"ტელეფონზე გაგრძელება"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"მიკროფონი მიუწვდომელია"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV-ს პარამეტრები მიუწვდომელია"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"ტაბლეტის პარამეტრები მიუწვდომელია"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"ტელეფონის პარამეტრები მიუწვდომელია"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"ამჟამად ამ აპზე თქვენი <xliff:g id="DEVICE">%1$s</xliff:g>-დან წვდომა შეუძლებელია. ცადეთ Android TV მოწყობილობიდან."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"ამჟამად ამ აპზე თქვენი <xliff:g id="DEVICE">%1$s</xliff:g>-დან წვდომა შეუძლებელია. ცადეთ ტაბლეტიდან."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"ამჟამად ამ აპზე თქვენი <xliff:g id="DEVICE">%1$s</xliff:g>-დან წვდომა შეუძლებელია. ცადეთ ტელეფონიდან."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"ამჟამად ამ აპზე თქვენი <xliff:g id="DEVICE">%1$s</xliff:g>-დან წვდომა შეუძლებელია. ცადეთ Android TV მოწყობილობიდან."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"ამჟამად ამ აპზე თქვენი <xliff:g id="DEVICE">%1$s</xliff:g>-დან წვდომა შეუძლებელია. ცადეთ ტაბლეტიდან."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"ამჟამად ამ აპზე თქვენი <xliff:g id="DEVICE">%1$s</xliff:g>-დან წვდომა შეუძლებელია. ცადეთ ტელეფონიდან."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"ეს აპი დამატებით უსაფრთხოებას ითხოვს. ცადეთ Android TV მოწყობილობიდან."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"ეს აპი დამატებით უსაფრთხოებას ითხოვს. ცადეთ ტაბლეტიდან."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"ეს აპი დამატებით უსაფრთხოებას ითხოვს. ცადეთ ტელეფონიდან."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ეს აპი Android-ის ძველი ვერსიისთვის შეიქმნა და შესაძლოა სათანადოდ არ მუშაობდეს. გადაამოწმეთ განახლებები ან დაუკავშირდით დეველოპერს."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"განახლების შემოწმება"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"თქვენ ახალი შეტყობინებები გაქვთ"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"შეეხეთ მეტის გასაგებად და შესაცვლელად."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"„არ შემაწუხოთ“ რეჟიმი შეცვლილია"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"შეეხეთ იმის სანახავად, თუ რა არის დაბლოკილი."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"შეტყობინების პარამეტრების შემოწმება"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13-ზე შეტყობინებების გასაგზავნად საჭიროა თქვენ მიერ დაინსტალირებული აპებისთვის ნებართვის მინიჭება. არსებული აპებისთვის ამ ნებართვის შესაცვლელად შეეხეთ."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"შემახსენე მოგვიან."</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"უარყოფა"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"სისტემა"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"პარამეტრები"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"კამერა"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> ნათარგმნია."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"შეტყობინება ნათარგმნია <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>-დან შემდეგ ენაზე: <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"აქტივობა ფონურ რეჟიმში"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"აპი იყენებს ბატარეას"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"აპი ბატარეას ხარჯავს"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"აპი კვლავ აქტიურია"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> იყენებს ბატარეას ფონში შეეხეთ გადასახედად."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> გაშვებულია ფონურ რეჟიმში შეეხეთ, რომ მართოთ ბატარეის მოხმარება."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> იმოქმედებს ბატარეის მუშაობის ხანგრძლივობაზე. შეეხეთ აქტიური აპების მიმოხილვისთვის."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"აქტიური აპების შემოწმება"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"ტელეფონის კამერაზე წვდომა ვერ მოხერხდა თქვენი <xliff:g id="DEVICE">%1$s</xliff:g>-დან"</string> diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml index 7fd0bebc0266..a21479f30767 100644 --- a/core/res/res/values-kk/strings.xml +++ b/core/res/res/values-kk/strings.xml @@ -2067,14 +2067,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Толығырақ ақпарат алу және өзгерту үшін түртіңіз."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Мазаламау режимі өзгерді"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Түймені түртіп, неге тыйым салынатынын көріңіз."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Хабарландыру параметрлерін қарау"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13 нұсқасында орнатылатын қолданбалар үшін хабарландырулар жіберу рұқсаты керек. Бұрынғы қолданбаларда осы рұқсатты өзгерту үшін түртіңіз."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Кейінірек еске салу"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Жабу"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Жүйе"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Параметрлер"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Камера"</string> @@ -2090,7 +2086,7 @@ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"Жарайды"</string> <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Өшіру"</string> <string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Толығырақ"</string> - <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Android 12 жүйесінде кеңейтілген хабарландырулар функциясы бейімделетін хабарландырулар функциясын алмастырды. Бұл функция ұсынылған әрекеттер мен жауаптарды көрсетіп, хабарландыруларыңызды ретке келтіреді.\n\nОл хабарландыру мазмұнын, соның ішінде жеке ақпаратыңызды (мысалы, контакт аттары мен хабарлар) пайдалана алады. Сондай-ақ бұл функция арқылы хабарландыруларды жабуға немесе оларға жауап беруге (мысалы, телефон қоңырауларына жауап беру және Мазаламау режимін басқару) болады."</string> + <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Android 12 жүйесінде \"Бейімделетін хабарландырулар\" функциясын \"Кеңейтілген хабарландырулар\" алмастырды. Бұл функция ұсынылған әрекеттер мен жауаптарды көрсетіп, хабарландыруларыңызды ретке келтіреді.\n\nОл хабарландыру мазмұнын, соның ішінде жеке ақпаратыңызды (мысалы, контакт аттары мен хабарларды) пайдалана алады. Сондай-ақ бұл функция арқылы хабарландыруларды жабуға немесе оларға жауап беруге (мысалы, телефон қоңырауларына жауап беруге және Мазаламау режимін басқаруға) болады."</string> <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Режим туралы хабарландыру"</string> <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Батарея заряды азаюы мүмкін"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Батарея ұзаққа жетуі үшін, Батареяны үнемдеу режимі іске қосылды"</string> @@ -2293,9 +2289,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"\"<xliff:g id="MESSAGE">%1$s</xliff:g>\" хабары аударылды."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Хабар мына тілге аударылды: <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>. Түпнұсқаның тілі: <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Фондық режимдегі әрекет"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Қолданба батареяны пайдаланып жатыр"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Қолданба әлі белсенді"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> қолданбасы батареяны фондық режимде пайдаланып жатыр. Көру үшін түртіңіз."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> қолданбасы батарея жұмысының ұзақтығына әсер етуі мүмкін. Белсенді қолданбаларды қарап шығу үшін түртіңіз."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Белсенді қолданбаларды тексеру"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"<xliff:g id="DEVICE">%1$s</xliff:g> құрылғысынан телефон камерасын пайдалану мүмкін емес."</string> diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml index 870571515cc6..bf0f8dbb1572 100644 --- a/core/res/res/values-km/strings.xml +++ b/core/res/res/values-km/strings.xml @@ -1141,7 +1141,7 @@ <string name="textSelectionCABTitle" msgid="5151441579532476940">"ការជ្រើសអត្ថបទ"</string> <string name="addToDictionary" msgid="8041821113480950096">"បន្ថែមទៅវចនានុក្រម"</string> <string name="deleteText" msgid="4200807474529938112">"លុប"</string> - <string name="inputMethod" msgid="1784759500516314751">"វិធីសាស្ត្របញ្ចូល"</string> + <string name="inputMethod" msgid="1784759500516314751">"វិធីបញ្ចូល"</string> <string name="editTextMenuTitle" msgid="857666911134482176">"សកម្មភាពអត្ថបទ"</string> <string name="input_method_nav_back_button_desc" msgid="3655838793765691787">"ថយក្រោយ"</string> <string name="input_method_ime_switch_button_desc" msgid="2736542240252198501">"ប្ដូរវិធីសាស្ត្របញ្ចូល"</string> @@ -1472,7 +1472,7 @@ <string name="permission_request_notification_for_app_with_subtitle" msgid="1298704005732851350">"ការអនុញ្ញាតដែលស្នើដោយ <xliff:g id="APP">%1$s</xliff:g>\nសម្រាប់គណនី <xliff:g id="ACCOUNT">%2$s</xliff:g>។"</string> <string name="forward_intent_to_owner" msgid="4620359037192871015">"អ្នកកំពុងប្រើកម្មវិធីនេះនៅខាងក្រៅប្រវត្តិរូបការងាររបស់អ្នក"</string> <string name="forward_intent_to_work" msgid="3620262405636021151">"អ្នកកំពុងប្រើកម្មវិធីនេះក្នុងប្រវត្តិរូបការងាររបស់អ្នក"</string> - <string name="input_method_binding_label" msgid="1166731601721983656">"វិធីសាស្ត្របញ្ចូល"</string> + <string name="input_method_binding_label" msgid="1166731601721983656">"វិធីបញ្ចូល"</string> <string name="sync_binding_label" msgid="469249309424662147">"ធ្វើសមកាលកម្ម"</string> <string name="accessibility_binding_label" msgid="1974602776545801715">"ភាពងាយស្រួល"</string> <string name="wallpaper_binding_label" msgid="1197440498000786738">"ផ្ទាំងរូបភាព"</string> @@ -1695,7 +1695,7 @@ <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"បិទផ្លូវកាត់"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"ប្រើប្រាស់ផ្លូវកាត់"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"បញ្ច្រាសពណ៌"</string> - <string name="color_correction_feature_name" msgid="3655077237805422597">"ការកែពណ៌"</string> + <string name="color_correction_feature_name" msgid="3655077237805422597">"ការកែតម្រូវពណ៌"</string> <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"មុខងារប្រើដៃម្ខាង"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ពន្លឺតិចខ្លាំង"</string> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"បានសង្កត់គ្រាប់ចុចកម្រិតសំឡេងជាប់។ បានបើក <xliff:g id="SERVICE_NAME">%1$s</xliff:g>។"</string> @@ -1839,7 +1839,7 @@ <string name="select_day" msgid="2060371240117403147">"ជ្រើសខែ និងថ្ងៃ"</string> <string name="select_year" msgid="1868350712095595393">"ជ្រើសឆ្នាំ"</string> <string name="deleted_key" msgid="9130083334943364001">"បានលុប <xliff:g id="KEY">%1$s</xliff:g>"</string> - <string name="managed_profile_label_badge" msgid="6762559569999499495">"កន្លែងធ្វើការ <xliff:g id="LABEL">%1$s</xliff:g>"</string> + <string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g>ការងារ"</string> <string name="managed_profile_label_badge_2" msgid="5673187309555352550">"<xliff:g id="LABEL">%1$s</xliff:g> ការងារទី 2"</string> <string name="managed_profile_label_badge_3" msgid="6882151970556391957">"<xliff:g id="LABEL">%1$s</xliff:g> ការងារទី 3"</string> <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"សួររកកូដ PIN មុនពេលដកខ្ទាស់"</string> @@ -1851,7 +1851,7 @@ <string name="confirm_battery_saver" msgid="5247976246208245754">"យល់ព្រម"</string> <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"មុខងារសន្សំថ្មបើករចនាប័ទ្មងងឹត និងដាក់កំហិត ឬបិទសកម្មភាពផ្ទៃខាងក្រោយ ឥទ្ធិពលរូបភាពមួយចំនួន មុខងារជាក់លាក់ និងការតភ្ជាប់បណ្ដាញមួយចំនួន។"</string> <string name="battery_saver_description" msgid="8518809702138617167">"មុខងារសន្សំថ្មបើករចនាប័ទ្មងងឹត និងដាក់កំហិត ឬបិទសកម្មភាពផ្ទៃខាងក្រោយ ឥទ្ធិពលរូបភាពមួយចំនួន មុខងារជាក់លាក់ និងការតភ្ជាប់បណ្ដាញមួយចំនួន។"</string> - <string name="data_saver_description" msgid="4995164271550590517">"ដើម្បីជួយកាត់បន្ថយការប្រើប្រាស់ទិន្នន័យ កម្មវិធីសន្សំសំចៃទិន្នន័យរារាំងកម្មវិធីមួយចំនួនមិនឲ្យបញ្ជូន ឬទទួលទិន្នន័យនៅផ្ទៃខាងក្រោយទេ។ កម្មវិធីដែលអ្នកកំពុងប្រើនាពេលបច្ចុប្បន្នអាចចូលប្រើប្រាស់ទិន្នន័យបាន ប៉ុន្តែអាចនឹងមិនញឹកញាប់ដូចមុនទេ។ ឧទាហរណ៍ រូបភាពមិនបង្ហាញទេ លុះត្រាតែអ្នកប៉ះរូបភាពទាំងនោះ។"</string> + <string name="data_saver_description" msgid="4995164271550590517">"ដើម្បីជួយកាត់បន្ថយការប្រើប្រាស់ទិន្នន័យ មុខងារសន្សំសំចៃទិន្នន័យរារាំងកម្មវិធីមួយចំនួនមិនឲ្យបញ្ជូន ឬទទួលទិន្នន័យនៅផ្ទៃខាងក្រោយទេ។ កម្មវិធីដែលអ្នកកំពុងប្រើនាពេលបច្ចុប្បន្នអាចចូលប្រើប្រាស់ទិន្នន័យបាន ប៉ុន្តែអាចនឹងមិនញឹកញាប់ដូចមុនទេ។ ឧទាហរណ៍ រូបភាពមិនបង្ហាញទេ លុះត្រាតែអ្នកប៉ះរូបភាពទាំងនោះ។"</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"បើកកម្មវិធីសន្សំសំចៃទិន្នន័យ?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"បើក"</string> <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{រយៈពេលមួយនាទី (រហូតដល់ {formattedTime})}other{រយៈពេល # នាទី (រហូតដល់ {formattedTime})}}"</string> @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"មិនអាចប្រើ <xliff:g id="APP_NAME">%1$s</xliff:g> នៅពេលនេះបានទេ។"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"មិនអាចប្រើ <xliff:g id="ACTIVITY">%1$s</xliff:g> បានទេ"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"តម្រូវឱ្យមានការអនុញ្ញាត"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"មិនអាចប្រើកាមេរ៉ាបានទេ"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"បន្តនៅលើទូរសព្ទ"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"មិនអាចប្រើមីក្រូហ្វូនបានទេ"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"មិនអាចប្រើការកំណត់ Android TV បានទេ"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"មិនអាចប្រើការកំណត់ថេប្លេតបានទេ"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"មិនអាចប្រើការកំណត់ទូរសព្ទបានទេ"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"មិនអាចចូលប្រើកម្មវិធីនេះនៅលើ <xliff:g id="DEVICE">%1$s</xliff:g> របស់អ្នកទេ។ សូមសាកល្បងប្រើនៅលើឧបករណ៍ Android TV របស់អ្នកជំនួសវិញ។"</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"មិនអាចចូលប្រើកម្មវិធីនេះនៅលើ <xliff:g id="DEVICE">%1$s</xliff:g> របស់អ្នកទេ។ សូមសាកល្បងប្រើនៅលើថេប្លេតរបស់អ្នកជំនួសវិញ។"</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"មិនអាចចូលប្រើកម្មវិធីនេះនៅលើ <xliff:g id="DEVICE">%1$s</xliff:g> របស់អ្នកទេ។ សូមសាកល្បងប្រើនៅលើទូរសព្ទរបស់អ្នកជំនួសវិញ។"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"មិនអាចប្រើកម្មវិធីនេះនៅលើ <xliff:g id="DEVICE">%1$s</xliff:g> របស់អ្នកនៅពេលនេះបានទេ។ សូមសាកល្បងប្រើនៅលើឧបករណ៍ Android TV របស់អ្នកជំនួសវិញ។"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"មិនអាចប្រើកម្មវិធីនេះនៅលើ <xliff:g id="DEVICE">%1$s</xliff:g> របស់អ្នកនៅពេលនេះបានទេ។ សូមសាកល្បងប្រើនៅលើថេប្លេតរបស់អ្នកជំនួសវិញ។"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"មិនអាចប្រើកម្មវិធីនេះនៅលើ <xliff:g id="DEVICE">%1$s</xliff:g> របស់អ្នកនៅពេលនេះបានទេ។ សូមសាកល្បងប្រើនៅលើទូរសព្ទរបស់អ្នកជំនួសវិញ។"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"កម្មវិធីនេះកំពុងស្នើសុំសុវត្ថិភាពបន្ថែម។ សូមសាកល្បងប្រើនៅលើឧបករណ៍ Android TV របស់អ្នកជំនួសវិញ។"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"កម្មវិធីនេះកំពុងស្នើសុំសុវត្ថិភាពបន្ថែម។ សូមសាកល្បងប្រើនៅលើថេប្លេតរបស់អ្នកជំនួសវិញ។"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"កម្មវិធីនេះកំពុងស្នើសុំសុវត្ថិភាពបន្ថែម។ សូមសាកល្បងប្រើនៅលើទូរសព្ទរបស់អ្នកជំនួសវិញ។"</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"កម្មវិធីនេះត្រូវបានបង្កើតឡើងសម្រាប់កំណែប្រព័ន្ធប្រតិបត្តិការ Android ចាស់ ហើយវាអាចដំណើរការខុសប្រក្រតី។ សូមសាកល្បងពិនិត្យមើលកំណែថ្មី ឬទាក់ទងទៅអ្នកអភិវឌ្ឍន៍។"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"រកមើលកំណែថ្មី"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"អ្នកមានសារថ្មី"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"ចុចដើម្បីស្វែងយល់បន្ថែម និងផ្លាស់ប្ដូរ។"</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"មុខងារកុំរំខានត្រូវបានប្ដូរ"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"សូមចុចដើម្បីមើលថាបានទប់ស្កាត់អ្វីខ្លះ។"</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"ពិនិត្យមើលការកំណត់ការជូនដំណឹង"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"ក្នុង Android 13 កម្មវិធីដែលអ្នកដំឡើងត្រូវការការអនុញ្ញាតរបស់អ្នក ដើម្បីផ្ញើការជូនដំណឹង។ សូមចុចដើម្បីផ្លាស់ប្ដូរការអនុញ្ញាតនេះសម្រាប់កម្មវិធីដែលមានស្រាប់។"</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"រំលឹកខ្ញុំពេលក្រោយ"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"ច្រានចោល"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"ប្រព័ន្ធ"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"ការកំណត់"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"កាមេរ៉ា"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"បានបកប្រែ <xliff:g id="MESSAGE">%1$s</xliff:g>។"</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"បានបកប្រែសារពីភាសា<xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>ទៅភាសា<xliff:g id="TO_LANGUAGE">%2$s</xliff:g>។"</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"សកម្មភាពនៅផ្ទៃខាងក្រោយ"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"កម្មវិធីកំពុងប្រើថ្ម"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"កម្មវិធីមួយកំពុងធ្វើឱ្យឆាប់អស់ថ្ម"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"កម្មវិធីនៅតែសកម្មដដែល"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> កំពុងប្រើថ្មនៅផ្ទៃខាងក្រោយ។ សូមចុច ដើម្បីពិនិត្យមើល។"</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> កំពុងដំណើរការនៅផ្ទៃខាងក្រោយ។ សូមចុចដើម្បីគ្រប់គ្រងការប្រើប្រាស់ថ្ម។"</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> អាចប៉ះពាល់ដល់កម្រិតថាមពលថ្ម។ សូមចុច ដើម្បីពិនិត្យមើលកម្មវិធីដែលសកម្ម។"</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"ពិនិត្យមើលកម្មវិធីសកម្ម"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"មិនអាចចូលប្រើកាមេរ៉ាទូរសព្ទពី <xliff:g id="DEVICE">%1$s</xliff:g> របស់អ្នកបានទេ"</string> diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml index a6148d983525..d415d800827d 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಇದೀಗ ಲಭ್ಯವಿಲ್ಲ."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ಲಭ್ಯವಿಲ್ಲ"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"ಅನುಮತಿಯ ಅಗತ್ಯವಿದೆ"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"ಕ್ಯಾಮರಾ ಲಭ್ಯವಿಲ್ಲ"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"ಫೋನ್ನಲ್ಲಿ ಮುಂದುವರಿಸಿ"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"ಮೈಕ್ರೊಫೋನ್ ಲಭ್ಯವಿಲ್ಲ"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV ಸೆಟ್ಟಿಂಗ್ಗಳು ಲಭ್ಯವಿಲ್ಲ"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"ಟ್ಯಾಬ್ಲೆಟ್ ಸೆಟ್ಟಿಂಗ್ಗಳು ಲಭ್ಯವಿಲ್ಲ"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"ಫೋನ್ ಸೆಟ್ಟಿಂಗ್ಗಳು ಲಭ್ಯವಿಲ್ಲ"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"ನಿಮ್ಮ <xliff:g id="DEVICE">%1$s</xliff:g> ನಲ್ಲಿ ಇದನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ಅದರ ಬದಲು ನಿಮ್ಮ Android TV ಸಾಧನದಲ್ಲಿ ಪ್ರಯತ್ನಿಸಿ."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"ನಿಮ್ಮ <xliff:g id="DEVICE">%1$s</xliff:g> ನಲ್ಲಿ ಇದನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ಅದರ ಬದಲು ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್ನಲ್ಲಿ ಪ್ರಯತ್ನಿಸಿ."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"ನಿಮ್ಮ <xliff:g id="DEVICE">%1$s</xliff:g> ನಲ್ಲಿ ಇದನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ಅದರ ಬದಲು ನಿಮ್ಮ ಫೋನ್ನಲ್ಲಿ ಪ್ರಯತ್ನಿಸಿ."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"ಈ ಸಮಯದಲ್ಲಿ ನಿಮ್ಮ <xliff:g id="DEVICE">%1$s</xliff:g> ನಲ್ಲಿ ಇದನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ಅದರ ಬದಲು ನಿಮ್ಮ Android TV ಸಾಧನದಲ್ಲಿ ಪ್ರಯತ್ನಿಸಿ."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"ಈ ಸಮಯದಲ್ಲಿ ನಿಮ್ಮ <xliff:g id="DEVICE">%1$s</xliff:g> ನಲ್ಲಿ ಇದನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ಅದರ ಬದಲು ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್ನಲ್ಲಿ ಪ್ರಯತ್ನಿಸಿ."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"ಈ ಸಮಯದಲ್ಲಿ ನಿಮ್ಮ <xliff:g id="DEVICE">%1$s</xliff:g> ನಲ್ಲಿ ಇದನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ಅದರ ಬದಲು ನಿಮ್ಮ ಫೋನ್ನಲ್ಲಿ ಪ್ರಯತ್ನಿಸಿ."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"ಈ ಆ್ಯಪ್ ಹೆಚ್ಚುವರಿ ಭದ್ರತೆಯನ್ನು ವಿನಂತಿಸುತ್ತಿದೆ. ಅದರ ಬದಲು ನಿಮ್ಮ Android TV ಸಾಧನದಲ್ಲಿ ಪ್ರಯತ್ನಿಸಿ."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"ಈ ಆ್ಯಪ್ ಹೆಚ್ಚುವರಿ ಭದ್ರತೆಯನ್ನು ವಿನಂತಿಸುತ್ತಿದೆ. ಅದರ ಬದಲು ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್ನಲ್ಲಿ ಪ್ರಯತ್ನಿಸಿ."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"ಈ ಆ್ಯಪ್ ಹೆಚ್ಚುವರಿ ಭದ್ರತೆಯನ್ನು ವಿನಂತಿಸುತ್ತಿದೆ. ಅದರ ಬದಲು ನಿಮ್ಮ ಫೋನ್ನಲ್ಲಿ ಪ್ರಯತ್ನಿಸಿ."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು Android ನ ಹಳೆಯ ಆವೃತ್ತಿಗೆ ರಚಿಸಲಾಗಿದೆ ಮತ್ತು ಸರಿಯಾಗಿ ಕೆಲಸ ಮಾಡದಿರಬಹುದು. ಅಪ್ಡೇಟ್ಗಳನ್ನು ಪರಿಶೀಲಿಸಲು ಪ್ರಯತ್ನಿಸಿ ಅಥವಾ ಡೆವಲಪರ್ ಅನ್ನು ಸಂಪರ್ಕಿಸಿ."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ಅಪ್ಡೇಟ್ಗಾಗಿ ಪರಿಶೀಲಿಸಿ"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"ನೀವು ಹೊಸ ಸಂದೇಶಗಳನ್ನು ಹೊಂದಿರುವಿರಿ"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"ಇನ್ನಷ್ಟು ತಿಳಿಯಲು ಮತ್ತು ಬದಲಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಬದಲಾಗಿದೆ"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"ಏನನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ ಎಂಬುದನ್ನು ಪರೀಕ್ಷಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"ಅಧಿಸೂಚನೆ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13 ನಲ್ಲಿ, ನೀವು ಇನ್ಸ್ಟಾಲ್ ಮಾಡುವ ಆ್ಯಪ್ಗಳಿಗೆ, ಅಧಿಸೂಚನೆಗಳನ್ನು ಕಳುಹಿಸಲು ನಿಮ್ಮ ಅನುಮತಿಯ ಅಗತ್ಯವಿದೆ. ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಆ್ಯಪ್ಗಳ ಅನುಮತಿಗಳನ್ನು ಬದಲಾಯಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"ನಂತರ ರಿಮೈಂಡ್ ಮಾಡಿ"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"ವಜಾಗೊಳಿಸಿ"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"ಸಿಸ್ಟಂ"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"ಸೆಟ್ಟಿಂಗ್ಗಳು"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"ಕ್ಯಾಮರಾ"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> ಅನ್ನು ಅನುವಾದಿಸಲಾಗಿದೆ."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"<xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> ಭಾಷೆಯಿಂದ <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> ಭಾಷೆಗೆ ಸಂದೇಶವನ್ನು ಅನುವಾದಿಸಲಾಗಿದೆ."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"ಹಿನ್ನೆಲೆ ಚಟುವಟಿಕೆ"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"ಒಂದು ಆ್ಯಪ್ ಬ್ಯಾಟರಿಯನ್ನು ಬಳಸುತ್ತಿದೆ"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"ಒಂದು ಆ್ಯಪ್ ಬ್ಯಾಟರಿಯನ್ನು ಹೆಚ್ಚು ಬಳಸುತ್ತಿದೆ"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"ಒಂದು ಆ್ಯಪ್ ಈಗಲೂ ಸಕ್ರಿಯವಾಗಿದೆ"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> ಹಿನ್ನೆಲೆಯಲ್ಲಿ ಬ್ಯಾಟರಿಯನ್ನು ಬಳಸುತ್ತಿದೆ. ಪರಿಶೀಲಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> ಹಿನ್ನೆಲೆಯಲ್ಲಿ ರನ್ ಆಗುತ್ತಿದೆ. ಬ್ಯಾಟರಿ ಬಳಕೆಯನ್ನು ನಿರ್ವಹಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಬಾಳಿಕೆಯ ಮೇಲೆ ಪ್ರಭಾವ ಬೀರಬಹುದು. ಸಕ್ರಿಯ ಆ್ಯಪ್ಗಳನ್ನು ಪರಿಶೀಲಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"ಸಕ್ರಿಯ ಆ್ಯಪ್ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"ನಿಮ್ಮ <xliff:g id="DEVICE">%1$s</xliff:g> ಮೂಲಕ ಫೋನ್ನ ಕ್ಯಾಮರಾವನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 3b5518a0706e..b34d17e859d7 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"현재 <xliff:g id="APP_NAME">%1$s</xliff:g> 앱을 사용할 수 없습니다."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> 사용할 수 없음"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"권한이 필요함"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"카메라를 사용할 수 없음"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"휴대전화에서 진행하기"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"마이크를 사용할 수 없음"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV 설정을 사용할 수 없음"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"태블릿 설정을 사용할 수 없음"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"휴대전화 설정을 사용할 수 없음"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"<xliff:g id="DEVICE">%1$s</xliff:g>에서 앱에 액세스할 수 없습니다. 대신 Android TV 기기에서 시도해 보세요."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"<xliff:g id="DEVICE">%1$s</xliff:g>에서 앱에 액세스할 수 없습니다. 대신 태블릿에서 시도해 보세요."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"<xliff:g id="DEVICE">%1$s</xliff:g>에서 앱에 액세스할 수 없습니다. 대신 휴대전화에서 시도해 보세요."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"현재 <xliff:g id="DEVICE">%1$s</xliff:g>에서 앱에 액세스할 수 없습니다. 대신 Android TV 기기에서 시도해 보세요."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"현재 <xliff:g id="DEVICE">%1$s</xliff:g>에서 앱에 액세스할 수 없습니다. 대신 태블릿에서 시도해 보세요."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"현재 <xliff:g id="DEVICE">%1$s</xliff:g>에서 앱에 액세스할 수 없습니다. 대신 휴대전화에서 시도해 보세요."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"앱에서 추가 보안을 요청합니다. 대신 Android TV 기기에서 시도해 보세요."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"앱에서 추가 보안을 요청합니다. 대신 태블릿에서 시도해 보세요."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"앱에서 추가 보안을 요청합니다. 대신 휴대전화에서 시도해 보세요."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"이 앱은 Android 이전 버전에 맞게 개발되었기 때문에 제대로 작동하지 않을 수 있습니다. 업데이트를 확인하거나 개발자에게 문의하세요."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"업데이트 확인"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"새 메시지 있음"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"자세히 알아보고 변경하려면 탭하세요."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"방해 금지 모드 변경"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"차단된 항목을 확인하려면 탭하세요."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"알림 설정 검토"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13에 설치된 앱에는 알림을 전송하기 위한 권한이 필요합니다. 기존 앱의 알림 전송 권한을 변경하려면 탭하세요."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"나중에 알림"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"닫기"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"시스템"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"설정"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"카메라"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"다음 메시지가 번역되었습니다. <xliff:g id="MESSAGE">%1$s</xliff:g>"</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"메시지가 <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>에서 <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>로 번역되었습니다."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"백그라운드 활동"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"앱이 배터리를 사용 중임"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"앱이 여전히 활성 상태임"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> 앱이 백그라운드에서 배터리를 사용하고 있습니다. 확인하려면 탭하세요."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> 앱은 배터리 수명에 영향을 미칠 수 있습니다. 활성 상태인 앱을 확인하려면 탭하세요."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"활성 상태의 앱 확인"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"사용자의 <xliff:g id="DEVICE">%1$s</xliff:g>에서 휴대전화 카메라에 액세스할 수 없습니다."</string> diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml index f56abd555236..76956575f6c4 100644 --- a/core/res/res/values-ky/strings.xml +++ b/core/res/res/values-ky/strings.xml @@ -402,7 +402,7 @@ <string name="permlab_getPackageSize" msgid="375391550792886641">"колдонмо сактагычынын мейкиндигин өлчөө"</string> <string name="permdesc_getPackageSize" msgid="742743530909966782">"Колдонмого өз кодун, дайындарын жана кэш өлчөмдөрүн түшүрүп алуу мүмкүнчүлүгүн берет"</string> <string name="permlab_writeSettings" msgid="8057285063719277394">"система тууралоолорун өзгөртүү"</string> - <string name="permdesc_writeSettings" msgid="8293047411196067188">"Колдонмого тутумдун коопсуздук жөндөөлөрүнүн дайындарын өзгөртүү мүмкүнчүлүгүн берет. Кесепттүү колдонмолор тутумуңуздун конфигурациясын бузуп салышы мүмкүн."</string> + <string name="permdesc_writeSettings" msgid="8293047411196067188">"Колдонмого системанын коопсуздук жөндөөлөрүнүн дайындарын өзгөртүү мүмкүнчүлүгүн берет. Кесепттүү колдонмолор тутумуңуздун конфигурациясын бузуп салышы мүмкүн."</string> <string name="permlab_receiveBootCompleted" msgid="6643339400247325379">"түзмөктү жандырганда иштеп баштоо"</string> <string name="permdesc_receiveBootCompleted" product="tablet" msgid="5565659082718177484">"Колдонмого тутум жүктөлүп бүтөөрү менен өзүн-өзү иштетүү мүмкүнчүлүгүн берет. Бул планшеттин ишке киргизилишин кыйла создуктуруп, планшеттин үзгүлтүксүз иштешин жайлатып салышы мүмкүн."</string> <string name="permdesc_receiveBootCompleted" product="tv" msgid="4900842256047614307">"Тутум күйгүзүлөрү менен колдонмого өз алдынча иштеп баштоого уруксат берет. Ага байланыштуу Android TV түзмөгүңүз кечирээк күйгүзүлүп, ошондой эле колдонмо такай иштеп тургандыктан, түзмөк жайыраак иштеп калышы мүмкүн."</string> @@ -425,10 +425,10 @@ <string name="permdesc_writeCallLog" product="tablet" msgid="2657525794731690397">"Колдонмого планшетиңиздин чалуулар тизмегин, анын ичинде, чыгыш жана кириш чалууларына тиешелүү берилиштерди өзгөртүү уруксатын берет. Зыяндуу колдонмолор муну колдонуп чалуулар тизмегин өзгөртө же жок кыла алышат."</string> <string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"Колдонмого Android TV түзмөгүңүздүн чалуулар тизмесин, анын ичинде кирүүчү жана чыгуучу чалуулар тууралуу маалыматтарды өзгөртүүгө уруксат берет. Зыянкеч колдонмолор ал уруксатты колдонуп чалуулар тизмеңизди тазалап же өзгөртүп коюшу мүмкүн."</string> <string name="permdesc_writeCallLog" product="default" msgid="5903033505665134802">"Колдонмого телефонуңуздун чалуулар тизмегин, анын ичинде, чыгыш жана кириш чалууларына тиешелүү берилиштерди өзгөртүү уруксатын берет. Зыяндуу колдонмолор муну колдонуп чалуулар тизмегин өзгөртө же жок кыла алышат."</string> - <string name="permlab_bodySensors" msgid="662918578601619569">"Иштеп жатканда дене сенсорлорунун дайындарын, мисалы, жүрөктүн согушун көрүү"</string> - <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Иштеп жатканда колдонмо дене сенсорлорунун дайындарын, мисалы, жүрөктүн согушу, температура жана кандагы кычкылтектин пайызын көрө алат."</string> - <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Фондо дене сенсорлорунун дайындарын, мисалы, жүрөктүн согушун көрүү"</string> - <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Колдонмо фондо дене сенсорлорунун дайындарын, мисалы, жүрөктүн согушу, температура жана кандагы кычкылтектин пайызын көрө алат."</string> + <string name="permlab_bodySensors" msgid="662918578601619569">"Иштеп жатканда дене сенсорлорунун көрсөткүчтөрүн, мисалы, жүрөктүн согушун көрүү"</string> + <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Иштеп жатканда колдонмо дене сенсорлорунун көрсөткүчтөрүн, мисалы, жүрөктүн согушу, температура жана кандагы кычкылтектин пайызын көрө алат."</string> + <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Фондо дене сенсорлорунун көрсөткүчтөрүн, мисалы, жүрөктүн согушун көрүү"</string> + <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Колдонмо фондо дене сенсорлорунун көрсөткүчтөрүн, мисалы, жүрөктүн согушу, температура жана кандагы кычкылтектин пайызын көрө алат."</string> <string name="permlab_readCalendar" msgid="6408654259475396200">"Жылнаамадагы иш-чараларды жана алардын чоо-жайын окуу"</string> <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Бул колдонмо планшетиңизде сакталган жылнаамадагы иш-чаралардын баарын окуп жана андагы маалыматтарды бөлүшүп же сактай алат."</string> <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Бул колдонмо Android TV түзмөгүңүздө сакталган жылнаама иш-чараларынын баарын окуп, ошондой эле жылнаама дайындарын бөлүшүп же сактай алат."</string> @@ -459,8 +459,8 @@ <string name="permdesc_camera" msgid="5240801376168647151">"Бул колдонмо иштеп жатканда камера менен сүрөт же видеолорду тарта алат."</string> <string name="permlab_backgroundCamera" msgid="7549917926079731681">"Фондо сүрөткө жана видеого тартат"</string> <string name="permdesc_backgroundCamera" msgid="1615291686191138250">"Бул колдонмо каалаган убакта камера менен сүрөт же видеолорду тарта алат."</string> - <string name="permlab_systemCamera" msgid="3642917457796210580">"Сүрөткө тартып, видеолорду жаздыруу үчүн бул колдонмого же кызматка тутумдун камерасын колдонууга уруксат берүү"</string> - <string name="permdesc_systemCamera" msgid="5938360914419175986">"Бул артыкчылыктуу тутум колдонмосу тутумдун камерасын каалаган убакта колдонуп, сүрөткө тартып, видео жаздыра алат. Ошондой эле колдонмого android.permission.CAMERA уруксатын берүү керек"</string> + <string name="permlab_systemCamera" msgid="3642917457796210580">"Сүрөткө тартып, видеолорду жаздыруу үчүн бул колдонмого же кызматка системанын камерасын колдонууга уруксат берүү"</string> + <string name="permdesc_systemCamera" msgid="5938360914419175986">"Бул артыкчылыктуу тутум колдонмосу системанын камерасын каалаган убакта колдонуп, сүрөткө тартып, видео жаздыра алат. Ошондой эле колдонмого android.permission.CAMERA уруксатын берүү керек"</string> <string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"Колдонмого же кызматка камера ачылып же жабылып жатканда чалууларды кабыл алууга уруксат берүү."</string> <string name="permdesc_cameraOpenCloseListener" msgid="2002636131008772908">"Бул колдонмо камера ачылып (аны ачып жаткан колдонмо көрсөтүлгөндө) же жабылып жатканда чалууларды кабыл алат."</string> <string name="permlab_vibrate" msgid="8596800035791962017">"титирөөнү башкаруу"</string> @@ -497,7 +497,7 @@ <string name="permdesc_transmitIr" product="tv" msgid="3278506969529173281">"Колдонмого Android TV түзмөгүңүздүн инфракызыл өткөргүчүн колдонууга уруксат берет."</string> <string name="permdesc_transmitIr" product="default" msgid="8484193849295581808">"Колдонмого телефондун инфракызыл өткөргүчүн колдонуу мүмкүнчүлүгүн берет."</string> <string name="permlab_setWallpaper" msgid="6959514622698794511">"тушкагаз коюу"</string> - <string name="permdesc_setWallpaper" msgid="2973996714129021397">"Колдонмого тутумдун тушкагазын коюу мүмкүнчүлүгүн берет."</string> + <string name="permdesc_setWallpaper" msgid="2973996714129021397">"Колдонмого системанын тушкагазын коюу мүмкүнчүлүгүн берет."</string> <string name="permlab_setWallpaperHints" msgid="1153485176642032714">"тушкагазыңыздын өлчөмүн өзгөртүү"</string> <string name="permdesc_setWallpaperHints" msgid="6257053376990044668">"Колдонмого тутум тушкагазынын өлчөмдөрүн коюу мүмкүнчүлүгүн берет."</string> <string name="permlab_setTimeZone" msgid="7922618798611542432">"убакыт алкагын коюу"</string> @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> учурда жеткиликсиз"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> жеткиликсиз"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Уруксат керек"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Камера жеткиликсиз"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Телефондон улантуу"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Микрофон жеткиликсиз"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV параметрлери жеткиликсиз"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Планшеттин параметрлери жеткиликсиз"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Телефондун параметрлери жеткиликсиз"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Буга <xliff:g id="DEVICE">%1$s</xliff:g> түзмөгүңүздөн кире албайсыз. Android TV түзмөгүңүздөн аракет кылып көрүңүз."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Буга <xliff:g id="DEVICE">%1$s</xliff:g> түзмөгүңүздөн кире албайсыз. Планшетиңизден кирип көрүңүз."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Буга <xliff:g id="DEVICE">%1$s</xliff:g> түзмөгүңүздөн кире албайсыз. Анын ордуна телефондон кирип көрүңүз."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Учурда буга <xliff:g id="DEVICE">%1$s</xliff:g> түзмөгүңүздөн кире албайсыз. Android TV түзмөгүңүздөн аракет кылып көрүңүз."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Учурда буга <xliff:g id="DEVICE">%1$s</xliff:g> түзмөгүңүздөн кире албайсыз. Планшетиңизден кирип көрүңүз."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Учурда буга <xliff:g id="DEVICE">%1$s</xliff:g> түзмөгүңүздөн кире албайсыз. Анын ордуна телефондон кирип көрүңүз."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Бул колдонмо кошумча коопсуздукту иштетүүнү суранып жатат. Android TV түзмөгүңүздөн аракет кылып көрүңүз."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Бул колдонмо кошумча коопсуздукту иштетүүнү суранып жатат. Планшетиңизден кирип көрүңүз."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Бул колдонмо кошумча коопсуздукту иштетүүнү суранып жатат. Анын ордуна телефондон кирип көрүңүз."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Бул колдонмо Android\'дин эски версиясы үчүн иштеп чыгарылган, андыктан туура эмес иштеши мүмкүн. Жаңыртууларды издеп көрүңүз же иштеп чыгуучуга кайрылыңыз."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Жаңыртууларды текшерүү"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Сизге жаңы билдирүүлөр келди"</string> @@ -2289,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Билдирүү (<xliff:g id="MESSAGE">%1$s</xliff:g>) которулду."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Билдирүү <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> тилинен <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> тилине которулду."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Фондогу активдүүлүк"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Колдонмо батареяны сарптоодо"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Колдонмо батареяны отургузууда"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Колдонмо дагы эле иштеп жатат"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> батареяны фондо колдонуп жатат. Көрүү үчүн таптап коюңуз."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> фондо иштеп жатат. Батареянын колдонулушун башкаруу үчүн таптап коюңуз."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> батареянын кубатынын мөөнөтүн азайтышы мүмкүн. Жигердүү колдонмолорду көрүү үчүн таптап коюңуз."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Жигердүү колдонмолорду карап чыгуу"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"<xliff:g id="DEVICE">%1$s</xliff:g> түзмөгүңүздөн телефондун камерасына мүмкүнчүлүк жок"</string> diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml index f1e5888d61b9..ca549aeba1f5 100644 --- a/core/res/res/values-land/dimens.xml +++ b/core/res/res/values-land/dimens.xml @@ -27,6 +27,8 @@ <dimen name="password_keyboard_spacebar_vertical_correction">2dip</dimen> <dimen name="preference_widget_width">72dp</dimen> + <!-- Height of the status bar --> + <dimen name="status_bar_height">@dimen/status_bar_height_landscape</dimen> <!-- Height of area above QQS where battery/time go --> <dimen name="quick_qs_offset_height">48dp</dimen> <!-- Default height of an action bar. --> diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml index 545b2dc64d88..cb8a77df06b3 100644 --- a/core/res/res/values-lo/strings.xml +++ b/core/res/res/values-lo/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ່ສາມາດໃຊ້ໄດ້ໃນຕອນນີ້."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"ບໍ່ສາມາດໃຊ້ <xliff:g id="ACTIVITY">%1$s</xliff:g> ໄດ້"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"ຕ້ອງມີການອະນຸຍາດ"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"ກ້ອງຖ່າຍຮູບບໍ່ສາມາດໃຊ້ໄດ້"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"ສືບຕໍ່ຢູ່ໂທລະສັບ"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"ໄມໂຄຣໂຟນບໍ່ສາມາດໃຊ້ໄດ້"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"ການຕັ້ງຄ່າ Android TV ບໍ່ສາມາດໃຊ້ໄດ້"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"ການຕັ້ງຄ່າແທັບເລັດບໍ່ສາມາດໃຊ້ໄດ້"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"ການຕັ້ງຄ່າໂທລະສັບບໍ່ສາມາດໃຊ້ໄດ້"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"ບໍ່ສາມາດເຂົ້າເຖິງແອັບນີ້ໄດ້ຢູ່ <xliff:g id="DEVICE">%1$s</xliff:g> ຂອງທ່ານ. ກະລຸນາລອງໃຊ້ຢູ່ອຸປະກອນ Android TV ຂອງທ່ານແທນ."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"ບໍ່ສາມາດເຂົ້າເຖິງແອັບນີ້ໄດ້ຢູ່ <xliff:g id="DEVICE">%1$s</xliff:g> ຂອງທ່ານ. ກະລຸນາລອງຢູ່ແທັບເລັດຂອງທ່ານແທນ."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"ບໍ່ສາມາດເຂົ້າເຖິງແອັບນີ້ໄດ້ຢູ່ <xliff:g id="DEVICE">%1$s</xliff:g> ຂອງທ່ານ. ກະລຸນາລອງຢູ່ໂທລະສັບຂອງທ່ານແທນ."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"ບໍ່ສາມາດເຂົ້າເຖິງແອັບນີ້ໄດ້ຢູ່ <xliff:g id="DEVICE">%1$s</xliff:g> ຂອງທ່ານໃນຕອນນີ້. ກະລຸນາລອງໃຊ້ຢູ່ອຸປະກອນ Android TV ຂອງທ່ານແທນ."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"ບໍ່ສາມາດເຂົ້າເຖິງແອັບນີ້ໄດ້ຢູ່ <xliff:g id="DEVICE">%1$s</xliff:g> ຂອງທ່ານໃນຕອນນີ້. ກະລຸນາລອງຢູ່ແທັບເລັດຂອງທ່ານແທນ."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"ບໍ່ສາມາດເຂົ້າເຖິງແອັບນີ້ໄດ້ຢູ່ <xliff:g id="DEVICE">%1$s</xliff:g> ຂອງທ່ານໃນຕອນນີ້. ກະລຸນາລອງຢູ່ໂທລະສັບຂອງທ່ານແທນ."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"ແອັບນີ້ກຳລັງຮ້ອງຂໍຄວາມປອດໄພເພີ່ມເຕີມ. ກະລຸນາລອງໃຊ້ຢູ່ອຸປະກອນ Android TV ຂອງທ່ານແທນ."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"ແອັບນີ້ກຳລັງຮ້ອງຂໍຄວາມປອດໄພເພີ່ມເຕີມ. ກະລຸນາລອງຢູ່ແທັບເລັດຂອງທ່ານແທນ."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"ແອັບນີ້ກຳລັງຮ້ອງຂໍຄວາມປອດໄພເພີ່ມເຕີມ. ກະລຸນາລອງຢູ່ໂທລະສັບຂອງທ່ານແທນ."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ແອັບນີ້ຖືກສ້າງຂຶ້ນສຳລັບ Android ເວີຊັນທີ່ເກົ່າກວ່າ ແລະ ອາດເຮັດວຽກໄດ້ບໍ່ປົກກະຕິ. ໃຫ້ລອງກວດສອບເບິ່ງອັບເດດ ຫຼື ຕິດຕໍ່ຜູ້ພັດທະນາ."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ກວດເບິ່ງອັບເດດ"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"ທ່ານມີຂໍ້ຄວາມໃໝ່"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"ແຕະເພື່ອສຶກສາເພີ່ມເຕີມ ແລະ ປ່ຽນແປງ."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"ປ່ຽນໂໝດຫ້າມລົບກວນແລ້ວ"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"ແຕະເພື່ອກວດສອບວ່າມີຫຍັງຖືກບລັອກໄວ້ແດ່."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"ກວດສອບການຕັ້ງຄ່າການແຈ້ງເຕືອນ"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"ໃນ Android 13, ແອັບຕ່າງໆທີ່ທ່ານຕິດຕັ້ງຈະຕ້ອງໃຊ້ການອະນຸຍາດຂອງທ່ານເພື່ອສົ່ງການແຈ້ງເຕືອນ. ແຕະເພື່ອປ່ຽນການອະນຸຍາດນີ້ສຳລັບແອັບທີ່ມີຢູ່ກ່ອນແລ້ວ."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"ແຈ້ງເຕືອນຂ້ອຍພາຍຫຼັງ"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"ປິດໄວ້"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"ລະບົບ"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"ການຕັ້ງຄ່າ"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"ກ້ອງ"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"ແປ <xliff:g id="MESSAGE">%1$s</xliff:g> ແລ້ວ."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"ແປຂໍ້ຄວາມຈາກ <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> ເປັນ <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> ແລ້ວ."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"ການເຄື່ອນໄຫວໃນພື້ນຫຼັງ"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"ມີແອັບກຳລັງໃຊ້ແບັດເຕີຣີ"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"ມີແອັບທີ່ຍັງຄົງນຳໃຊ້ຢູ່"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> ກຳລັງໃຊ້ແບັດເຕີຣີໃນພື້ນຫຼັງ. ແຕະເພື່ອກວດສອບ."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> ອາດສົ່ງຜົນກະທົບຕໍ່ອາຍຸແບັດເຕີຣີ. ແຕະເພື່ອກວດສອບແອັບທີ່ນຳໃຊ້ຢູ່."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"ກວດສອບແອັບທີ່ເຄື່ອນໄຫວ"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"ບໍ່ສາມາດເຂົ້າເຖິງກ້ອງຖ່າຍຮູບຂອງໂທລະສັບຈາກ <xliff:g id="DEVICE">%1$s</xliff:g> ຂອງທ່ານໄດ້"</string> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index f0a6a0ff7dbf..f2ce117330d0 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -1935,36 +1935,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ šiuo metu nepasiekiama."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"„<xliff:g id="ACTIVITY">%1$s</xliff:g>“ nepasiekiama"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Reikalingas leidimas"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kamera nepasiekiama"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Tęsti telefone"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofonas nepasiekiamas"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"„Android TV“ nustatymai nepasiekiami"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Planšetinio kompiuterio nustatymai nepasiekiami"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Telefono nustatymai nepasiekiami"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Nepavyksta pasiekti programos iš jūsų „<xliff:g id="DEVICE">%1$s</xliff:g>“. Pabandykite naudoti „Android TV“ įrenginį."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Nepavyksta pasiekti programos iš jūsų „<xliff:g id="DEVICE">%1$s</xliff:g>“. Pabandykite naudoti planšetinį kompiuterį."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Nepavyksta pasiekti programos iš jūsų „<xliff:g id="DEVICE">%1$s</xliff:g>“. Pabandykite naudoti telefoną."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Šįkart nepavyksta pasiekti programos iš jūsų „<xliff:g id="DEVICE">%1$s</xliff:g>“. Pabandykite naudoti „Android TV“ įrenginį."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Šįkart nepavyksta pasiekti programos iš jūsų „<xliff:g id="DEVICE">%1$s</xliff:g>“. Pabandykite naudoti planšetinį kompiuterį."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Šįkart nepavyksta pasiekti programos iš jūsų „<xliff:g id="DEVICE">%1$s</xliff:g>“. Pabandykite naudoti telefoną."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Ši programa prašo papildomų saugos funkcijų. Pabandykite naudoti „Android TV“ įrenginį."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Ši programa prašo papildomų saugos funkcijų. Pabandykite naudoti planšetinį kompiuterį."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Ši programa prašo papildomų saugos funkcijų. Pabandykite naudoti telefoną."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ši programa sukurta naudoti senesnės versijos sistemoje „Android“ ir gali tinkamai neveikti. Pabandykite patikrinti, ar yra naujinių, arba susisiekite su kūrėju."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Tikrinti, ar yra naujinių"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Turite naujų pranešimų"</string> @@ -2069,14 +2054,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Palieskite, kad sužinotumėte daugiau ir pakeistumėte."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Netrukdymo režimas pakeistas"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Palieskite, kad patikrintumėte, kas blokuojama."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Peržiūrėkite pranešimų nustatymus"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"13 versijos „Android” jūsų įdiegtoms programoms reikia suteikti leidimą siųsti pranešimus. Palieskite, kad pakeistumėte šį leidimą esamoms programoms."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Priminti vėliau"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Atsisakyti"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Sistema"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Nustatymai"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Fotoaparatas"</string> @@ -2295,9 +2276,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Pranešimas „<xliff:g id="MESSAGE">%1$s</xliff:g>“ išverstas."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Pranešimas išverstas iš <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> į <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Veikla fone"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Programa eikvoja akumuliatoriaus energiją"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Programa vis dar aktyvi"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"Programa „<xliff:g id="APP">%1$s</xliff:g>“ eikvoja akumuliatoriaus energiją fone. Palieskite ir peržiūrėkite."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"Programa „<xliff:g id="APP">%1$s</xliff:g>“ gali turėti įtakos akumuliatoriaus veikimo laikui. Palieskite ir peržiūrėkite aktyvias programas."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Peržiūrėkite aktyvias programas"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Nepavyko pasiekti telefono fotoaparato iš „<xliff:g id="DEVICE">%1$s</xliff:g>“"</string> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index 086af664a6c0..12b41462e969 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -1689,7 +1689,7 @@ <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"Neatļaut"</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Pieskarieties funkcijai, lai sāktu to izmantot"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Izvēlieties funkcijas, ko izmantot ar pieejamības pogu"</string> - <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Izvēlieties funkcijas, ko izmantot ar skaļuma pogu īsinājumtaustiņu"</string> + <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Izvēlieties funkcijas, ko izmantot ar skaļuma pogu saīsni"</string> <string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Pakalpojums <xliff:g id="SERVICE_NAME">%s</xliff:g> ir izslēgts."</string> <string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Rediģēt īsinājumtaustiņus"</string> <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gatavs"</string> @@ -1934,36 +1934,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> pašlaik nav pieejama."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> nav pieejams"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Nepieciešama atļauja"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kamera nav pieejama"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Turpiniet tālrunī"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofons nav pieejams"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV iestatījumi nav pieejami"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Planšetdatora iestatījumi nav pieejami"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Tālruņa iestatījumi nav pieejami"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Šajā ierīcē (<xliff:g id="DEVICE">%1$s</xliff:g>) nevar piekļūt šai lietotnei. Mēģiniet tai piekļūt savā Android TV ierīcē."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Šajā ierīcē (<xliff:g id="DEVICE">%1$s</xliff:g>) nevar piekļūt šai lietotnei. Mēģiniet tai piekļūt savā planšetdatorā."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Šajā ierīcē (<xliff:g id="DEVICE">%1$s</xliff:g>) nevar piekļūt šai lietotnei. Mēģiniet tai piekļūt savā tālrunī."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Šajā ierīcē (<xliff:g id="DEVICE">%1$s</xliff:g>) pašlaik nevar piekļūt šai lietotnei. Mēģiniet tai piekļūt savā Android TV ierīcē."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Šajā ierīcē (<xliff:g id="DEVICE">%1$s</xliff:g>) pašlaik nevar piekļūt šai lietotnei. Mēģiniet tai piekļūt savā planšetdatorā."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Šajā ierīcē (<xliff:g id="DEVICE">%1$s</xliff:g>) pašlaik nevar piekļūt šai lietotnei. Mēģiniet tai piekļūt savā tālrunī."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Šī lietotne pieprasa papildu drošību. Mēģiniet tai piekļūt savā Android TV ierīcē."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Šī lietotne pieprasa papildu drošību. Mēģiniet tai piekļūt savā planšetdatorā."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Šī lietotne pieprasa papildu drošību. Mēģiniet tai piekļūt savā tālrunī."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Šī lietotne tika izstrādāta vecākai Android versijai un var nedarboties pareizi. Meklējiet atjauninājumus vai sazinieties ar izstrādātāju."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Meklēt atjauninājumu"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Jums ir jaunas īsziņas."</string> @@ -2068,14 +2053,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Pieskarieties, lai uzzinātu vairāk un veiktu izmaiņas."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Režīms “Netraucēt” ir mainīts"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Pieskarieties, lai uzzinātu, kas tiek bloķēts."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Pārskatīt paziņojumu iestatījumus"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Operētājsistēmā Android 13 jūsu instalētajām lietotnēm ir nepieciešama jūsu atļauja, lai sūtītu paziņojumus. Pieskarieties, lai mainītu šo atļauju esošajām lietotnēm."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Atgādināt vēlāk"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Noraidīt"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Sistēma"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Iestatījumi"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Kamera"</string> @@ -2294,9 +2275,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Iztulkots: <xliff:g id="MESSAGE">%1$s</xliff:g>."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Ziņojums ir iztulkots no šādas valodas: <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> šādā valodā: <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Darbība fonā"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Lietotne patērē akumulatora enerģiju"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Lietotne joprojām ir aktīva"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"Lietotne <xliff:g id="APP">%1$s</xliff:g> patērē akumulatora enerģiju fonā. Pieskarieties, lai pārskatītu."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"Lietotne <xliff:g id="APP">%1$s</xliff:g> var ietekmēt akumulatora darbības ilgumu. Pieskarieties, lai pārskatītu aktīvās lietotnes."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Pārbaudiet aktīvās lietotnes"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Nevar piekļūt tālruņa kamerai no jūsu ierīces (<xliff:g id="DEVICE">%1$s</xliff:g>)."</string> diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml index 81ecb7e696d1..e287a7af7482 100644 --- a/core/res/res/values-mk/strings.xml +++ b/core/res/res/values-mk/strings.xml @@ -1849,8 +1849,8 @@ <string name="package_updated_device_owner" msgid="7560272363805506941">"Ажурирано од администраторот"</string> <string name="package_deleted_device_owner" msgid="2292335928930293023">"Избришано од администраторот"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"Во ред"</string> - <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"„Штедачот на батерија“ вклучува темна тема и ја ограничува или исклучува активноста во заднина, некои визуелни ефекти, одредени функции и некои мрежни врски."</string> - <string name="battery_saver_description" msgid="8518809702138617167">"„Штедачот на батерија“ вклучува темна тема и ја ограничува или исклучува активноста во заднина, некои визуелни ефекти, одредени функции и некои мрежни врски."</string> + <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"„Штедачот на батерија“ вклучува „Темна тема“ и ограничува или исклучува активност во заднина, некои визуелни ефекти, одредени функции и некои мрежни врски."</string> + <string name="battery_saver_description" msgid="8518809702138617167">"„Штедачот на батерија“ вклучува „Темна тема“ и ограничува или исклучува активност во заднина, некои визуелни ефекти, одредени функции и некои мрежни врски."</string> <string name="data_saver_description" msgid="4995164271550590517">"За да се намали користењето интернет, „Штедачот на интернет“ спречува дел од апликациите да испраќаат или да примаат податоци во заднина. Одредена апликација што ја користите ќе може да користи интернет, но можеби тоа ќе го прави поретко. Ова значи, на пример, дека сликите нема да се прикажуваат додека не ги допрете."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Да се вклучи „Штедач на интернет“?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Вклучи"</string> @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> не е достапна во моментов."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> е недостапна"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Потребна е дозвола"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Камерата е недостапна"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Продолжете на телефонот"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Микрофонот не е достапен"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Поставките за Android TV не се достапни"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Поставките за таблетот не се достапни"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Поставките за телефонот не се достапни"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Ова не може да се отвори на <xliff:g id="DEVICE">%1$s</xliff:g>. Пробајте на вашиот Android TV како алтернатива."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Ова не може да се отвори на <xliff:g id="DEVICE">%1$s</xliff:g>. Пробајте на вашиот таблет како алтернатива."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Ова не може да се отвори на <xliff:g id="DEVICE">%1$s</xliff:g>. Пробајте на вашиот телефон како алтернатива."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Ова не може да се отвори на <xliff:g id="DEVICE">%1$s</xliff:g> во моментов. Пробајте на вашиот Android TV како алтернатива."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Ова не може да се отвори на <xliff:g id="DEVICE">%1$s</xliff:g> во моментов. Пробајте на вашиот таблет како алтернатива."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Ова не може да се отвори на <xliff:g id="DEVICE">%1$s</xliff:g> во моментов. Пробајте на вашиот телефон како алтернатива."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Апликацијава бара дополнителна безбедност. Пробајте на вашиот Android TV како алтернатива."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Апликацијава бара дополнителна безбедност. Пробајте на вашиот таблет како алтернатива."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Апликацијава бара дополнителна безбедност. Пробајте на вашиот телефон како алтернатива."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Апликацијава е создадена за постара верзија на Android и може да не функционира правилно. Проверете за ажурирања или контактирајте со програмерот."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Проверка за ажурирање"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Имате нови пораки"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Допрете за да дознаете повеќе и да ги промените поставките."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Поставките за „Не вознемирувај“ се изменија"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Допрете за да проверите што е блокирано."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Прегледајте ги поставките за известувања"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Во Android 13, на апликациите што ги инсталирате им е потребна ваша дозвола за испраќање известувања. Допрете за да ја промените оваа дозвола за постојни апликации."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Потсети ме подоцна"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Отфрли"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Систем"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Поставки"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Камера"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g>, преведено."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Пораката е преведена од <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> на <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Активност во заднина"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Апликација троши батерија"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Апликација ја празни батеријата"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Апликација сѐ уште е активна"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> троши батерија во заднина. Допрете за да прегледате."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> се извршува во заднина. Допрете за да управувате со користењето на батеријата."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> може да влијае врз траење на батеријата. Допрете за да ги прегледате активните апликации."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Проверете ги активните апликации"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Не може да се пристапи до камерата на вашиот телефон од <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml index 34e5116eb0e9..23236e08b869 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ഇപ്പോൾ ലഭ്യമല്ല."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ലഭ്യമല്ല"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"അനുമതി ആവശ്യമാണ്"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"ക്യാമറ ലഭ്യമല്ല"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"ഫോണിൽ തുടരുക"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"മൈക്രോഫോൺ ലഭ്യമല്ല"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV ക്രമീകരണം ലഭ്യമല്ല"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Tablet ക്രമീകരണം ലഭ്യമല്ല"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"ഫോൺ ക്രമീകരണം ലഭ്യമല്ല"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"നിങ്ങളുടെ <xliff:g id="DEVICE">%1$s</xliff:g> ഉപകരണത്തിൽ ഇത് ആക്സസ് ചെയ്യാനാകില്ല. പകരം നിങ്ങളുടെ Android TV ഉപകരണത്തിൽ ശ്രമിച്ച് നോക്കൂ."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"നിങ്ങളുടെ <xliff:g id="DEVICE">%1$s</xliff:g> ഉപകരണത്തിൽ ഇത് ആക്സസ് ചെയ്യാനാകില്ല. പകരം നിങ്ങളുടെ ടാബ്ലെറ്റിൽ ശ്രമിച്ച് നോക്കൂ."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"നിങ്ങളുടെ <xliff:g id="DEVICE">%1$s</xliff:g> ഉപകരണത്തിൽ ഇത് ആക്സസ് ചെയ്യാനാകില്ല. പകരം നിങ്ങളുടെ ഫോണിൽ ശ്രമിച്ച് നോക്കൂ."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"നിങ്ങളുടെ <xliff:g id="DEVICE">%1$s</xliff:g> ഉപകരണത്തിൽ ഇത് ഇപ്പോൾ ആക്സസ് ചെയ്യാനാകില്ല. പകരം നിങ്ങളുടെ Android TV ഉപകരണത്തിൽ ശ്രമിച്ച് നോക്കൂ."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"നിങ്ങളുടെ <xliff:g id="DEVICE">%1$s</xliff:g> ഉപകരണത്തിൽ ഇത് ഇപ്പോൾ ആക്സസ് ചെയ്യാനാകില്ല. പകരം നിങ്ങളുടെ ടാബ്ലെറ്റിൽ ശ്രമിച്ച് നോക്കൂ."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"നിങ്ങളുടെ <xliff:g id="DEVICE">%1$s</xliff:g> ഉപകരണത്തിൽ ഇത് ഇപ്പോൾ ആക്സസ് ചെയ്യാനാകില്ല. പകരം നിങ്ങളുടെ ഫോണിൽ ശ്രമിച്ച് നോക്കൂ."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"ഈ ആപ്പ് അധിക സുരക്ഷ അഭ്യർത്ഥിക്കുന്നു. പകരം നിങ്ങളുടെ Android TV ഉപകരണത്തിൽ ശ്രമിച്ച് നോക്കൂ."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"ഈ ആപ്പ് അധിക സുരക്ഷ അഭ്യർത്ഥിക്കുന്നു. പകരം നിങ്ങളുടെ ടാബ്ലെറ്റിൽ ശ്രമിച്ച് നോക്കൂ."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"ഈ ആപ്പ് അധിക സുരക്ഷ അഭ്യർത്ഥിക്കുന്നു. പകരം നിങ്ങളുടെ ഫോണിൽ ശ്രമിച്ച് നോക്കൂ."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ഈ ആപ്പ് Android-ന്റെ പഴയ പതിപ്പിനായി നിർമ്മിച്ചിരിക്കുന്നതിനാൽ ശരിയായി പ്രവർത്തിച്ചേക്കില്ല. അപ്ഡേറ്റിനായി പരിശോധിക്കുക, അല്ലെങ്കിൽ ഡെവലപ്പറുമായി ബന്ധപ്പെടുക."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"അപ്ഡേറ്റിനായി പരിശോധിക്കുക"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"നിങ്ങൾക്ക് പുതിയ സന്ദേശങ്ങൾ ഉണ്ട്"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"കൂടുതലറിയാനും മാറ്റാനും ടാപ്പ് ചെയ്യുക."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"\'ശല്യപ്പെടുത്തരുത്\' മാറ്റി"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"എന്തിനെയാണ് ബ്ലോക്ക് ചെയ്തതെന്ന് പരിശോധിക്കാൻ ടാപ്പ് ചെയ്യുക."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"അറിയിപ്പ് ക്രമീകരണം അവലോകനം ചെയ്യുക"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13-ൽ നിങ്ങൾ ഇൻസ്റ്റാൾ ചെയ്യുന്ന ആപ്പുകൾക്ക് അറിയിപ്പുകൾ അയയ്ക്കാൻ നിങ്ങളുടെ അനുമതി വേണം. നിലവിലുള്ള ആപ്പുകൾക്ക് ഈ അനുമതി മാറ്റാൻ ടാപ്പ് ചെയ്യുക."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"പിന്നീട് ഓർമ്മിപ്പിക്കൂ"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"ഡിസ്മിസ് ചെയ്യുക"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"സിസ്റ്റം"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"ക്രമീകരണം"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"ക്യാമറ"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> വിവർത്തനം ചെയ്തു."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"<xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> എന്നതിൽ നിന്ന് <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> എന്നതിലേക്ക് സന്ദേശം വിവർത്തനം ചെയ്തു."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"പശ്ചാത്തല ആക്റ്റിവിറ്റി"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"ഒരു ആപ്പ് ബാറ്ററി ഉപയോഗിക്കുന്നു"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"ഒരു ആപ്പ് ബാറ്ററി ഉപയോഗിച്ചുതീർക്കുന്നു"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"ഒരു ആപ്പ് ഇപ്പോഴും സജീവമാണ്"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> പശ്ചാത്തലത്തിൽ ബാറ്ററി ഉപയോഗിക്കുന്നു. അവലോകനം ചെയ്യാൻ ടാപ്പ് ചെയ്യുക."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> പശ്ചാത്തലത്തിൽ പ്രവർത്തിച്ചുകൊണ്ടിരിക്കുന്നു. ബാറ്ററി ഉപയോഗം മാനേജ് ചെയ്യാൻ ടാപ്പ് ചെയ്യുക."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> ബാറ്ററി ലൈഫിനെ ബാധിച്ചേക്കാം. സജീവ ആപ്പുകൾ അവലോകനം ചെയ്യാൻ ടാപ്പ് ചെയ്യുക."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"സജീവമായ ആപ്പുകൾ പരിശോധിക്കുക"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"നിങ്ങളുടെ <xliff:g id="DEVICE">%1$s</xliff:g> എന്നതിൽ നിന്ന് ഫോണിന്റെ ക്യാമറ ആക്സസ് ചെയ്യാനാകില്ല"</string> diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml index ecc1a7674446..45ee7549f757 100644 --- a/core/res/res/values-mn/strings.xml +++ b/core/res/res/values-mn/strings.xml @@ -307,9 +307,9 @@ <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS мессежийг илгээх, харах"</string> <string name="permgrouplab_storage" msgid="9173334109512154196">"Файл болон документ"</string> <string name="permgroupdesc_storage" msgid="8352226729501080525">"таны төхөөрөмж дээрх файл болон документод хандах"</string> - <string name="permgrouplab_readMediaAural" msgid="5885210465560755316">"Хөгжим & бусад аудио"</string> + <string name="permgrouplab_readMediaAural" msgid="5885210465560755316">"Хөгжим, бусад аудио"</string> <string name="permgroupdesc_readMediaAural" msgid="1170143315714662822">"таны төхөөрөмж дээрх аудио файлд хандах"</string> - <string name="permgrouplab_readMediaVisual" msgid="9137695801926624061">"Зураг & видео"</string> + <string name="permgrouplab_readMediaVisual" msgid="9137695801926624061">"Зураг, видео"</string> <string name="permgroupdesc_readMediaVisual" msgid="173787212014117477">"таны төхөөрөмж дээрх зураг болон видео файлд хандах"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"Микрофон"</string> <string name="permgroupdesc_microphone" msgid="1047786732792487722">"дуу хураах"</string> @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> яг одоо боломжгүй байна."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> боломжгүй байна"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Зөвшөөрөл шаардлагатай"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Камер боломжгүй байна"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Утсан дээр үргэлжлүүлэх"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Микрофон боломжгүй байна"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV-н тохиргоо боломжгүй байна"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Таблетын тохиргоо боломжгүй байна"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Утасны тохиргоо боломжгүй байна"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Үүнд таны <xliff:g id="DEVICE">%1$s</xliff:g>-с хандах боломжгүй. Оронд нь Android TV төхөөрөмж дээрээ туршиж үзнэ үү."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Үүнд таны <xliff:g id="DEVICE">%1$s</xliff:g>-с хандах боломжгүй. Оронд нь таблет дээрээ туршиж үзнэ үү."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Үүнд таны <xliff:g id="DEVICE">%1$s</xliff:g>-с хандах боломжгүй. Оронд нь утсан дээрээ туршиж үзнэ үү."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Одоогоор үүнд таны <xliff:g id="DEVICE">%1$s</xliff:g> дээрээс хандах боломжгүй. Оронд нь Android TV төхөөрөмж дээрээ туршиж үзнэ үү."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Одоогоор үүнд таны <xliff:g id="DEVICE">%1$s</xliff:g> дээрээс хандах боломжгүй. Оронд нь таблет дээрээ туршиж үзнэ үү."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Одоогоор үүнд таны <xliff:g id="DEVICE">%1$s</xliff:g> дээрээс хандах боломжгүй. Оронд нь утсан дээрээ туршиж үзнэ үү."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Энэ апп нэмэлт аюулгүй байдал хүсэж байна. Оронд нь Android TV төхөөрөмж дээрээ туршиж үзнэ үү."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Энэ апп нэмэлт аюулгүй байдал хүсэж байна. Оронд нь таблет дээрээ туршиж үзнэ үү."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Энэ апп нэмэлт аюулгүй байдал хүсэж байна. Оронд нь утсан дээрээ туршиж үзнэ үү."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Энэ аппыг Андройдын хуучин хувилбарт зориулсан бөгөөд буруу ажиллаж болзошгүй. Шинэчлэлтийг шалгаж эсвэл хөгжүүлэгчтэй холбогдоно уу."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Шинэчлэлтийг шалгах"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Танд шинэ мессежүүд байна"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Илүү ихийг мэдэж, өөрчлөхийн тулд товшино уу."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Бүү саад бол горимыг өөрчилсөн"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Блоклосон зүйлийг шалгахын тулд товшино уу."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Мэдэгдлийн тохиргоог шалгах"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13-т таны суулгасан аппууд мэдэгдэл илгээхийн тулд тэдгээрт таны зөвшөөрөл шаардлагатай. Одоо байгаа аппуудын уг зөвшөөрлийг өөрчлөхийн тулд товшино уу."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Надад дараа сануул"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Хаах"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Систем"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Тохиргоо"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Камер"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> Орчуулсан."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Мессежийг <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>-с <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> руу орчуулсан."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Дэвсгэрийн үйл ажиллагаа"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Апп батарейг ашиглаж байна"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Апп батарейг зарцуулж байна"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Апп идэвхтэй хэвээр байна"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"Ард <xliff:g id="APP">%1$s</xliff:g> батарейг ашиглаж байна. Хянахын тулд товшино уу."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> ард ажиллаж байна. Батарей ашиглалтыг удирдахын тулд товшино уу."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> батарейн ажиллах хугацаанд нөлөөлж болзошгүй. Идэвхтэй аппыг хянахын тулд товшино уу."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Идэвхтэй аппуудыг шалгах"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Таны <xliff:g id="DEVICE">%1$s</xliff:g>-с утасны камерт хандах боломжгүй"</string> diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml index 6741330183be..408a3ae55340 100644 --- a/core/res/res/values-mr/strings.xml +++ b/core/res/res/values-mr/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> आता उपलब्ध नाही."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> उपलब्ध नाही"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"परवानगी आवश्यक आहे"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"कॅमेरा उपलब्ध नाही"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"फोनवर पुढे सुरू ठेवा"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"मायक्रोफोन उपलब्ध नाही"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV सेटिंग्ज उपलब्ध नाहीत"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"टॅबलेट सेटिंग्ज उपलब्ध नाहीत"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"फोन सेटिंग्ज उपलब्ध नाहीत"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"हे तुमच्या <xliff:g id="DEVICE">%1$s</xliff:g> वर अॅक्सेस केले जाऊ शकत नाही. त्याऐवजी तुमच्या Android TV डिव्हाइसवर अॅक्सेस करून पहा."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"हे तुमच्या <xliff:g id="DEVICE">%1$s</xliff:g> वर अॅक्सेस केले जाऊ शकत नाही. त्याऐवजी तुमच्या टॅबलेटवर अॅक्सेस करून पहा."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"हे तुमच्या <xliff:g id="DEVICE">%1$s</xliff:g> वर अॅक्सेस केले जाऊ शकत नाही. त्याऐवजी तुमच्या फोनवर अॅक्सेस करून पहा."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"हे यावेळी तुमच्या <xliff:g id="DEVICE">%1$s</xliff:g> वर अॅक्सेस केले जाऊ शकत नाही. त्याऐवजी तुमच्या Android TV डिव्हाइसवर अॅक्सेस करून पहा."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"हे यावेळी तुमच्या <xliff:g id="DEVICE">%1$s</xliff:g> वर अॅक्सेस केले जाऊ शकत नाही. त्याऐवजी तुमच्या टॅबलेटवर अॅक्सेस करून पहा."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"हे यावेळी तुमच्या <xliff:g id="DEVICE">%1$s</xliff:g> वर अॅक्सेस केले जाऊ शकत नाही. त्याऐवजी तुमच्या फोनवर अॅक्सेस करून पहा."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"हे अॅप अतिरिक्त सुरक्षेची विनंती करत आहे. त्याऐवजी तुमच्या Android TV डिव्हाइसवर अॅक्सेस करून पहा."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"हे अॅप अतिरिक्त सुरक्षेची विनंती करत आहे. त्याऐवजी तुमच्या टॅबलेटवर अॅक्सेस करून पहा."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"हे अॅप अतिरिक्त सुरक्षेची विनंती करत आहे. त्याऐवजी तुमच्या फोनवर अॅक्सेस करून पहा."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"हे अॅप Android च्या जुन्या आवृत्ती साठी तयार करण्यात आले होते आणि योग्यरितीने कार्य करू शकणार नाही. अपडेट आहेत का ते तपासून पहा, किंवा डेव्हलपरशी संपर्क साधण्याचा प्रयत्न करा."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"अपडेटसाठी तपासा"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"आपल्याकडे नवीन मेसेज आहेत"</string> @@ -2289,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> चे भाषांतर केले."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"मेसेजचे <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> मधून <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> मध्ये भाषांतर केले."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"बॅकग्राउंड अॅक्टिव्हिटी"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"अॅप बॅटरी वापरत आहे"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"अॅप बॅटरी संपवत आहे"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"अॅप अजूनही अॅक्टिव्ह आहे"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> हे बॅकग्राउंडमध्ये बॅटरी वापरत आहे. पुनरावलोकन करण्यासाठी टॅप करा."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> बॅकग्राउंडमध्ये रन होत आहे. बॅटरी वापर व्यवस्थापित करण्यासाठी टॅप करा."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> कदाचित बॅटरी लाइफवर परिणाम करेल. अॅक्टिव्ह अॅप्सचे पुनरावलोकन करण्यासाठी टॅप करा."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"ॲक्टिव्ह ॲप्स पहा"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"तुमच्या <xliff:g id="DEVICE">%1$s</xliff:g> वरून फोनचा कॅमेरा अॅक्सेस करू शकत नाही"</string> diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml index 5a12e05f56d7..3a95c940a57d 100644 --- a/core/res/res/values-ms/strings.xml +++ b/core/res/res/values-ms/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak tersedia sekarang."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> tidak tersedia"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Kebenaran diperlukan"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kamera tidak tersedia"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Teruskan pada telefon"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofon tidak tersedia"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Tetapan Android TV tidak tersedia"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Tetapan tablet tidak tersedia"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Tetapan telefon tidak tersedia"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Apl ini tidak boleh diakses pada <xliff:g id="DEVICE">%1$s</xliff:g>. Cuba pada peranti Android TV anda."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Apl ini tidak boleh diakses pada <xliff:g id="DEVICE">%1$s</xliff:g>. Cuba pada tablet anda."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Apl ini tidak boleh diakses pada <xliff:g id="DEVICE">%1$s</xliff:g>. Cuba pada telefon anda."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Aplikasi ini tidak boleh diakses pada <xliff:g id="DEVICE">%1$s</xliff:g> anda pada masa ini. Cuba pada peranti Android TV anda."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Aplikasi ini tidak boleh diakses pada <xliff:g id="DEVICE">%1$s</xliff:g> anda pada masa ini. Cuba pada tablet anda."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Aplikasi ini tidak boleh diakses pada <xliff:g id="DEVICE">%1$s</xliff:g> anda pada masa ini. Cuba pada telefon anda."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Apl ini meminta keselamatan tambahan. Cuba pada peranti Android TV anda."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Apl ini meminta keselamatan tambahan. Cuba pada tablet anda."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Apl ini meminta keselamatan tambahan. Cuba pada telefon anda."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Apl ini dibina untuk versi Android yang lebih lama dan mungkin tidak berfungsi dengan betul. Cuba semak kemas kini atau hubungi pembangun."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Semak kemaskinian"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Anda mempunyai mesej baharu"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Ketik untuk mengetahui lebih lanjut dan menukar tetapan."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Jangan Ganggu telah berubah"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Ketik untuk menyemak item yang disekat."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Semak tetapan pemberitahuan"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Dalam Android 13, apl yang anda pasang memerlukan kebenaran anda untuk menghantar pemberitahuan. Ketik untuk menukar kebenaran ini bagi apl sedia ada."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Ingatkan saya nanti"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Ketepikan"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Sistem"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Tetapan"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Kamera"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> Diterjemahkan."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Mesej diterjemahkan daripada <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> kepada <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Aktiviti Latar Belakang"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Apl sedang menggunakan bateri"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Apl menyusutkan bateri"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Apl masih aktif"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> sedang menggunakan bateri pada latar. Ketik untuk menyemak."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> sedang berfungsi di latar. Ketik untuk mengurus penggunaan bateri."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> mungkin menjejaskan hayat bateri. Ketik untuk menyemak apl aktif."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Semak apl aktif"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Tidak dapat mengakses kamera telefon daripada <xliff:g id="DEVICE">%1$s</xliff:g> anda"</string> diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml index 3cf9bf0518fd..b655345d6714 100644 --- a/core/res/res/values-my/strings.xml +++ b/core/res/res/values-my/strings.xml @@ -1337,7 +1337,7 @@ <string name="carrier_app_notification_text" msgid="6567057546341958637">"၎င်းကိုတပ်ဆင်ရန် တို့ပါ"</string> <string name="time_picker_dialog_title" msgid="9053376764985220821">"အချိန်သတ်မှတ်ရန်"</string> <string name="date_picker_dialog_title" msgid="5030520449243071926">"ရက်စွဲ အတည်ပြုရန်"</string> - <string name="date_time_set" msgid="4603445265164486816">"အတည်ပြုရန်"</string> + <string name="date_time_set" msgid="4603445265164486816">"သတ်မှတ်ရန်"</string> <string name="date_time_done" msgid="8363155889402873463">"ပြီးပါပြီ"</string> <string name="perms_new_perm_prefix" msgid="6984556020395757087"><font size="12" fgcolor="#ff33b5e5">"အသစ်: "</font></string> <string name="perms_description_app" msgid="2747752389870161996">"<xliff:g id="APP_NAME">%1$s</xliff:g> မှ ထောက်ပံ့သည်"</string> @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ကို ယခု မရနိုင်ပါ။"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> မရနိုင်ပါ"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"ခွင့်ပြုချက်လိုအပ်သည်"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"ကင်မရာ မရနိုင်ပါ"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"ဖုန်းပေါ်တွင် ရှေ့ဆက်ပါ"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"မိုက်ခရိုဖုန်း မရနိုင်ပါ"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV ဆက်တင်များ မရနိုင်ပါ"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Tablet ဆက်တင်များ မရနိုင်ပါ"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Phone ဆက်တင်များ မရနိုင်ပါ"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"၎င်းကို သင်၏ <xliff:g id="DEVICE">%1$s</xliff:g> တွင် သုံး၍မရပါ။ Android TV စက်တွင် စမ်းကြည့်ပါ။"</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"၎င်းကို သင်၏ <xliff:g id="DEVICE">%1$s</xliff:g> တွင် သုံး၍မရပါ။ တက်ဘလက်တွင် စမ်းကြည့်ပါ။"</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"၎င်းကို သင်၏ <xliff:g id="DEVICE">%1$s</xliff:g> တွင် သုံး၍မရပါ။ ဖုန်းတွင် စမ်းကြည့်ပါ။"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"၎င်းကို သင်၏ <xliff:g id="DEVICE">%1$s</xliff:g> တွင် ယခုသုံး၍မရပါ။ Android TV စက်တွင် စမ်းကြည့်ပါ။"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"၎င်းကို သင်၏ <xliff:g id="DEVICE">%1$s</xliff:g> တွင် ယခုသုံး၍မရပါ။ တက်ဘလက်တွင် စမ်းကြည့်ပါ။"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"၎င်းကို သင်၏ <xliff:g id="DEVICE">%1$s</xliff:g> တွင် ယခုသုံး၍မရပါ။ ဖုန်းတွင် စမ်းကြည့်ပါ။"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"ဤအက်ပ်က ထပ်ဆောင်းလုံခြုံရေးကို တောင်းဆိုနေသည်။ Android TV စက်တွင် စမ်းကြည့်ပါ။"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"ဤအက်ပ်က ထပ်ဆောင်းလုံခြုံရေးကို တောင်းဆိုနေသည်။ တက်ဘလက်တွင် စမ်းကြည့်ပါ။"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"ဤအက်ပ်က ထပ်ဆောင်းလုံခြုံရေးကို တောင်းဆိုနေသည်။ ဖုန်းတွင် စမ်းကြည့်ပါ။"</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ဤအက်ပ်ကို Android ဗားရှင်းဟောင်းအတွက် ပြုလုပ်ထားခြင်းဖြစ်ပြီး ပုံမှန်အလုပ်မလုပ်နိုင်ပါ။ အပ်ဒိတ်များအတွက် ရှာကြည့်ပါ သို့မဟုတ် ဆော့ဖ်ဝဲအင်ဂျင်နီယာကို ဆက်သွယ်ပါ။"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"အပ်ဒိတ်စစ်ရန်"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"သင့်ထံတွင် စာအသစ်များရောက်နေသည်"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"ပိုမိုလေ့လာရန်နှင့် ပြောင်းလဲရန် တို့ပါ။"</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"\'မနှောင့်ယှက်ရ\' ပြောင်းလဲသွားပါပြီ"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"ပိတ်ထားသည့်အရာများကို ကြည့်ရန် တို့ပါ။"</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"အကြောင်းကြားချက် ဆက်တင်များ စိစစ်ရန်"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13 တွင် သင်ထည့်သွင်းသော အက်ပ်များသည် အကြောင်းကြားချက်များပို့ရန် သင်၏ခွင့်ပြုချက် လိုအပ်ပါမည်။ ရှိပြီးသားအက်ပ်များအတွက် ဤခွင့်ပြုချက်ကိုပြောင်းရန် တို့ပါ။"</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"နောက်မှ သတိပေးပါ"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"ပယ်ရန်"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"စနစ်"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"ဆက်တင်များ"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"ကင်မရာ"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> ကို ဘာသာပြန်ထားသည်။"</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"မက်ဆေ့ဂျ်ကို <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> မှ <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> သို့ ဘာသာပြန်ထားသည်။"</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"နောက်ခံလုပ်ဆောင်ချက်"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"အက်ပ်က ဘက်ထရီသုံးနေသည်"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"အက်ပ်က ဘက်ထရီအကုန်မြန်စေသည်"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"အက်ပ်က ပွင့်နေဆဲဖြစ်သည်"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> က နောက်ခံတွင် ဘက်ထရီသုံးနေသည်။ ပြန်ကြည့်ရန် တို့ပါ။"</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> ကို နောက်ခံတွင် ဖွင့်ထားသည်။ ဘက်ထရီ အသုံးပြုမှုကို စီမံရန် တို့ပါ။"</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> က ဘက်ထရီ သက်တမ်းကို ထိခိုက်နိုင်သည်။ ပွင့်နေသောအက်ပ်များ ပြန်ကြည့်ရန် တို့ပါ။"</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"ပွင့်နေသည့်အက်ပ်များ စစ်ဆေးရန်"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"သင်၏ <xliff:g id="DEVICE">%1$s</xliff:g> မှ ဖုန်းကင်မရာကို သုံး၍မရပါ"</string> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index 8e4c0800bb1e..2f495b0151b6 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> er ikke tilgjengelig for øyeblikket."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> er utilgjengelig"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Du må gi tillatelse"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kameraet er utilgjengelig"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Fortsett på telefonen"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofonen er utilgjengelig"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV-innstillingene er utilgjengelige"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Nettbrettinnstillingene er utilgjengelige"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Telefoninnstillingene er utilgjengelige"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Dette er ikke tilgjengelig på <xliff:g id="DEVICE">%1$s</xliff:g>. Prøv på Android TV-enheten din i stedet."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Dette er ikke tilgjengelig på <xliff:g id="DEVICE">%1$s</xliff:g>. Prøv på nettbrettet ditt i stedet."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Dette er ikke tilgjengelig på <xliff:g id="DEVICE">%1$s</xliff:g>. Prøv på telefonen din i stedet."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Dette er ikke tilgjengelig på <xliff:g id="DEVICE">%1$s</xliff:g> for øyeblikket. Prøv på Android TV-enheten din i stedet."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Dette er ikke tilgjengelig på <xliff:g id="DEVICE">%1$s</xliff:g> for øyeblikket. Prøv på nettbrettet ditt i stedet."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Dette er ikke tilgjengelig på <xliff:g id="DEVICE">%1$s</xliff:g> for øyeblikket. Prøv på telefonen din i stedet."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Denne appen ber om ekstra sikkerhet. Prøv på Android TV-enheten din i stedet."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Denne appen ber om ekstra sikkerhet. Prøv på nettbrettet ditt i stedet."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Denne appen ber om ekstra sikkerhet. Prøv på telefonen din i stedet."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Denne appen er utviklet for en eldre versjon av Android og fungerer kanskje ikke som den skal. Prøv å se etter oppdateringer, eller kontakt utvikleren."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Se etter oppdateringer"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Du har nye meldinger"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Trykk for å finne ut mer og endre."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Ikke forstyrr er endret"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Trykk for å sjekke hva som er blokkert."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Gjennomgå varslingsinnstillingene"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"I Android 13 må apper du installerer, få tillatelse til å sende varsler. Trykk for å endre denne tillatelsen for eksisterende apper."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Påminn meg senere"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Lukk"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"System"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Innstillinger"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Kamera"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> er oversatt."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Meldingen er oversatt fra <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> til <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Aktivitet i bakgrunnen"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"En app bruker batteri"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"En app er fremdeles aktiv"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> bruker batteri i bakgrunnen. Trykk for å gjennomgå."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> kan påvirke batterilevetiden. Trykk for å gjennomgå aktive apper."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Sjekk aktive apper"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Det er ikke mulig å få tilgang til telefonkameraet fra <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml index 66e0909f3c5a..1bcab4e85c78 100644 --- a/core/res/res/values-ne/strings.xml +++ b/core/res/res/values-ne/strings.xml @@ -1695,7 +1695,7 @@ <string name="disable_accessibility_shortcut" msgid="5806091378745232383">"सर्टकटलाई निष्क्रिय पार्नुहोस्"</string> <string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"सर्टकट प्रयोग गर्नुहोस्"</string> <string name="color_inversion_feature_name" msgid="326050048927789012">"कलर इन्भर्सन"</string> - <string name="color_correction_feature_name" msgid="3655077237805422597">"रङ्ग सच्याउने सुविधा"</string> + <string name="color_correction_feature_name" msgid="3655077237805422597">"कलर करेक्सन"</string> <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"एक हाते मोड"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"अझै मधुरो"</string> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> अन भयो।"</string> @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> अहिले उपलब्ध छैन।"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> उपलब्ध छैन"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"अनुमति चाहिन्छ"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"क्यामेरा उपलब्ध छैन"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"फोनमा जारी राख्नुहोस्"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"माइक्रोफोन उपलब्ध छैन"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV सम्बन्धी सेटिङ उपलब्ध छैनन्"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"ट्याब्लेटका सेटिङ उपलब्ध छैनन्"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"फोनका सेटिङ उपलब्ध छैनन्"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"हाल तपाईंको <xliff:g id="DEVICE">%1$s</xliff:g> मा यो एप चलाउन मिल्दैन। बरु तपाईंको Android TV डिभाइसमा स्ट्रिम गरी हेर्नुहोस्।"</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"हाल तपाईंको <xliff:g id="DEVICE">%1$s</xliff:g> मा यो एप चलाउन मिल्दैन। बरु तपाईंको ट्याब्लेटमा स्ट्रिम गरी हेर्नुहोस्।"</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"हाल तपाईंको <xliff:g id="DEVICE">%1$s</xliff:g> मा यो एप चलाउन मिल्दैन। बरु तपाईंको फोनमा स्ट्रिम गरी हेर्नुहोस्।"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"यस बखत तपाईंको <xliff:g id="DEVICE">%1$s</xliff:g> मा यो एप स्ट्रिम गर्न मिल्दैन। बरु तपाईंको Android TV डिभाइसमा स्ट्रिम गरी हेर्नुहोस्।"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"यस बखत तपाईंको <xliff:g id="DEVICE">%1$s</xliff:g> मा यो एप स्ट्रिम गर्न मिल्दैन। बरु तपाईंको ट्याब्लेटमा स्ट्रिम गरी हेर्नुहोस्।"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"यस बखत तपाईंको <xliff:g id="DEVICE">%1$s</xliff:g> मा यो एप स्ट्रिम गर्न मिल्दैन। बरु तपाईंको फोनमा स्ट्रिम गरी हेर्नुहोस्।"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"यो एपले सुरक्षासम्बन्धी अतिरिक्त सुविधा अन गर्न अनुरोध गरिरहेको छ। बरु तपाईंको Android TV डिभाइसमा स्ट्रिम गरी हेर्नुहोस्।"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"यो एपले सुरक्षासम्बन्धी अतिरिक्त सुविधा अन गर्न अनुरोध गरिरहेको छ। बरु तपाईंको ट्याब्लेटमा स्ट्रिम गरी हेर्नुहोस्।"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"यो एपले सुरक्षासम्बन्धी अतिरिक्त सुविधा अन गर्न अनुरोध गरिरहेको छ। बरु तपाईंको फोनमा स्ट्रिम गरी हेर्नुहोस्।"</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"यो एप Android को पुरानो संस्करणका लागि बनाइएको हुनाले यसले सही ढङ्गले काम नगर्न सक्छ। अद्यावधिकहरू उपलब्ध छन् वा छैनन् भनी जाँच गरी हेर्नुहोस् वा यसको विकासकर्तालाई सम्पर्क गर्नुहोस्।"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"अपडेट उपलब्ध छ वा छैन जाँच्नुहोस्"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"तपाईंलाई नयाँ सन्देश आएको छ"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"थप जान्न र परिवर्तन गर्न ट्याप गर्नुहोस्।"</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"बाधा नपुर्याउनुहोस् मोड परिवर्तन भएको छ"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"रोक लगाइएका कुराहरू जाँच गर्न ट्याप गर्नुहोस्।"</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"सूचनाका सेटिङको समीक्षा गर्नुहोस्"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android १३ मा तपाईंले अनुमति दिनुभएका खण्डमा मात्र तपाईंले इन्स्टल गर्नुभएका एपले सूचना पठाउन सक्छन्। यसअघि इन्स्टल गरिसकिएका एपका हकमा यो अनुमति परिवर्तन गर्न ट्याप गर्नुहोस्।"</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"मलाई पछि स्मरण गराइयोस्"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"हटाउनुहोस्"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"प्रणाली"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"सेटिङहरू"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"क्यामेरा"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> अनुवाद गरिएको छ।"</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"म्यासेज <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> भाषाबाट <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> भाषामा अनुवाद गरिएको छ।"</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"ब्याकग्राउन्डमा गरिएको क्रियाकलाप"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"कुनै एपले ब्याट्री खपत गरिरहेको छ"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"कुनै एप अझै पनि चलिरहेको छ"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> ले ब्याकग्राउन्डमा ब्याट्री खपत गरिरहेको छ। समीक्षा गर्न ट्याप गर्नुहोस्।"</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> ले ब्याट्रीको आयु घटाउन सक्छ। सक्रिय एपहरू हेर्न ट्याप गर्नुहोस्।"</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"कुन कुन एप सक्रिय छ भन्ने कुरा जाँच्नुहोस्"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"तपाईंको <xliff:g id="DEVICE">%1$s</xliff:g> मार्फत फोनको क्यामेरा प्रयोग गर्न मिल्दैन"</string> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index f7f6d6704d5a..93f96104bb63 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is momenteel niet beschikbaar."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> niet beschikbaar"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Rechten vereist"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Camera niet beschikbaar"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Doorgaan op telefoon"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Microfoon niet beschikbaar"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV-instellingen niet beschikbaar"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Tabletinstellingen niet beschikbaar"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Telefooninstellingen niet beschikbaar"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Je hebt hier geen toegang toe op je <xliff:g id="DEVICE">%1$s</xliff:g>. Probeer het in plaats daarvan op je Android TV-apparaat."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Je hebt hier geen toegang toe op je <xliff:g id="DEVICE">%1$s</xliff:g>. Probeer het in plaats daarvan op je tablet."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Je hebt hier geen toegang toe op je <xliff:g id="DEVICE">%1$s</xliff:g>. Probeer het in plaats daarvan op je telefoon."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Je hebt hier nu geen toegang toe op je <xliff:g id="DEVICE">%1$s</xliff:g>. Probeer het in plaats daarvan op je Android TV-apparaat."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Je hebt hier nu geen toegang toe op je <xliff:g id="DEVICE">%1$s</xliff:g>. Probeer het in plaats daarvan op je tablet."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Je hebt hier nu geen toegang toe op je <xliff:g id="DEVICE">%1$s</xliff:g>. Probeer het in plaats daarvan op je telefoon."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Deze app vraagt om aanvullende beveiliging. Probeer het in plaats daarvan op je Android TV-apparaat."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Deze app vraagt om aanvullende beveiliging. Probeer het in plaats daarvan op je tablet."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Deze app vraagt om aanvullende beveiliging. Probeer het in plaats daarvan op je telefoon."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Deze app is ontwikkeld voor een oudere versie van Android en werkt mogelijk niet op de juiste manier. Controleer op updates of neem contact op met de ontwikkelaar."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Controleren op update"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Je hebt nieuwe berichten"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Tik voor meer informatie en om te wijzigen."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"\'Niet storen\' is gewijzigd"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Tik om te controleren wat er is geblokkeerd."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Instellingen voor meldingen bekijken"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"In Android 13 hebben apps die je installeert je toestemming nodig om meldingen te sturen. Tik om deze toestemming voor bestaande apps te wijzigen."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Later herinneren"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Sluiten"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Systeem"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Instellingen"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Camera"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> vertaald."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Bericht vertaald vanuit het <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> naar het <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Achtergrondactiviteit"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Een app gebruikt de batterij"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Een app is nog actief"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> gebruikt de batterij op de achtergrond. Tik om te bekijken."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> kan van invloed zijn op de batterijduur. Tik om actieve apps te bekijken."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Actieve apps checken"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Kan geen toegang tot de camera van de telefoon krijgen vanaf je <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml index 4bd1dfb82eeb..6b58faf99960 100644 --- a/core/res/res/values-or/strings.xml +++ b/core/res/res/values-or/strings.xml @@ -1697,7 +1697,7 @@ <string name="color_inversion_feature_name" msgid="326050048927789012">"ରଙ୍ଗ ବଦଳାଇବାର ସୁବିଧା"</string> <string name="color_correction_feature_name" msgid="3655077237805422597">"ରଙ୍ଗ ସଂଶୋଧନ"</string> <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ଏକ-ହାତ ମୋଡ୍"</string> - <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ଅତିରିକ୍ତ ଡିମ୍"</string> + <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ଅତ୍ୟଧିକ ଡିମ"</string> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ଭଲ୍ୟୁମ୍ କୀ\'ଗୁଡ଼ିକୁ ଧରି ରଖାଯାଇଛି। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ଚାଲୁ ହୋଇଛି।"</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ଭଲ୍ୟୁମ୍ କୀ\'ଗୁଡ଼ିକୁ ଧରି ରଖାଯାଇଛି। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ବନ୍ଦ ହୋଇଛି।"</string> <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ବ୍ୟବହାର କରିବାକୁ ତିନି ସେକେଣ୍ଡ ପାଇଁ ଉଭୟ ଭଲ୍ୟୁମ୍ କୀ ଦବାଇ ଧରି ରଖନ୍ତୁ"</string> @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ବର୍ତ୍ତମାନ ଉପଲବ୍ଧ ନାହିଁ।"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ଉପଲବ୍ଧ ନାହିଁ"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"ଅନୁମତି ଆବଶ୍ୟକ"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"କ୍ୟାମେରା ଉପଲବ୍ଧ ନାହିଁ"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"ଫୋନରେ ଜାରି ରଖନ୍ତୁ"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"ମାଇକ୍ରୋଫୋନ ଉପଲବ୍ଧ ନାହିଁ"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV ସେଟିଂସ ଉପଲବ୍ଧ ନାହିଁ"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"ଟାବଲେଟ ସେଟିଂସ ଉପଲବ୍ଧ ନାହିଁ"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"ଫୋନ ସେଟିଂସ ଉପଲବ୍ଧ ନାହିଁ"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"ଏହାକୁ ଆପଣଙ୍କ <xliff:g id="DEVICE">%1$s</xliff:g>ରେ ଆକ୍ସେସ କରାଯାଇପାରିବ ନାହିଁ। ଏହା ପରିବର୍ତ୍ତେ ଆପଣଙ୍କ Android TV ଡିଭାଇସରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"ଏହାକୁ ଆପଣଙ୍କ <xliff:g id="DEVICE">%1$s</xliff:g>ରେ ଆକ୍ସେସ କରାଯାଇପାରିବ ନାହିଁ। ଏହା ପରିବର୍ତ୍ତେ ଆପଣଙ୍କ ଟାବଲେଟରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"ଏହାକୁ ଆପଣଙ୍କ <xliff:g id="DEVICE">%1$s</xliff:g>ରେ ଆକ୍ସେସ କରାଯାଇପାରିବ ନାହିଁ। ଏହା ପରିବର୍ତ୍ତେ ଆପଣଙ୍କ ଫୋନରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"ବର୍ତ୍ତମାନ ଏହାକୁ ଆପଣଙ୍କ <xliff:g id="DEVICE">%1$s</xliff:g>ରେ ଆକ୍ସେସ କରାଯାଇପାରିବ ନାହିଁ। ଏହା ପରିବର୍ତ୍ତେ ଆପଣଙ୍କ Android TV ଡିଭାଇସରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"ବର୍ତ୍ତମାନ ଏହାକୁ ଆପଣଙ୍କ <xliff:g id="DEVICE">%1$s</xliff:g>ରେ ଆକ୍ସେସ କରାଯାଇପାରିବ ନାହିଁ। ଏହା ପରିବର୍ତ୍ତେ ଆପଣଙ୍କ ଟାବଲେଟରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"ବର୍ତ୍ତମାନ ଏହାକୁ ଆପଣଙ୍କ <xliff:g id="DEVICE">%1$s</xliff:g>ରେ ଆକ୍ସେସ କରାଯାଇପାରିବ ନାହିଁ। ଏହା ପରିବର୍ତ୍ତେ ଆପଣଙ୍କ ଫୋନରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"ଏହି ଆପ ଅତିରିକ୍ତ ସୁରକ୍ଷା ପାଇଁ ଅନୁରୋଧ କରୁଛି। ଏହା ପରିବର୍ତ୍ତେ ଆପଣଙ୍କ Android TV ଡିଭାଇସରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"ଏହି ଆପ ଅତିରିକ୍ତ ସୁରକ୍ଷା ପାଇଁ ଅନୁରୋଧ କରୁଛି। ଏହା ପରିବର୍ତ୍ତେ ଆପଣଙ୍କ ଟାବଲେଟରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"ଏହି ଆପ ଅତିରିକ୍ତ ସୁରକ୍ଷା ପାଇଁ ଅନୁରୋଧ କରୁଛି। ଏହା ପରିବର୍ତ୍ତେ ଆପଣଙ୍କ ଫୋନରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ଏହି ଆପ୍କୁ Androidର ପୁରୁଣା ଭର୍ସନ୍ ପାଇଁ ନିର୍ମାଣ କରାଯାଇଥିଲା ଏବଂ ଠିକ୍ ଭାବେ କାମ କରିନପାରେ। ଏହାପାଇଁ ଅପଡେଟ୍ ଅଛି କି ନାହିଁ ଯାଞ୍ଚ କରନ୍ତୁ କିମ୍ବା ଡେଭେଲପର୍ଙ୍କ ସହିତ ସମ୍ପର୍କ କରନ୍ତୁ।"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ଅପଡେଟ୍ ପାଇଁ ଯାଞ୍ଚ କରନ୍ତୁ"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"ଆପଣଙ୍କ ପାଖରେ ନୂଆ ମେସେଜ୍ ରହିଛି"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"ଅଧିକ ଜାଣିବାକୁ ଟ୍ୟାପ୍ କରନ୍ତୁ ଏବଂ ବଦଳାନ୍ତୁ।"</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"’ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ’ ବଦଳିଯାଇଛି"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"କ’ଣ ଅବରୋଧ ହୋଇଛି ଯାଞ୍ଚ କରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"ବିଜ୍ଞପ୍ତି ସେଟିଂସକୁ ସମୀକ୍ଷା କରନ୍ତୁ"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13ରେ, ଆପଣ ଇନଷ୍ଟଲ କରୁଥିବା ଆପ୍ସ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ପଠାଇବା ପାଇଁ ଆପଣଙ୍କ ଅନୁମତି ଆବଶ୍ୟକ କରେ। ପୂର୍ବରୁ ଥିବା ଆପ୍ସ ପାଇଁ ଏହି ଅନୁମତିକୁ ପରିବର୍ତ୍ତନ କରିବାକୁ ଟାପ କରନ୍ତୁ।"</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"ମୋତେ ପରେ ରିମାଇଣ୍ଡ କର"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"ଖାରଜ କରନ୍ତୁ"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"ସିଷ୍ଟମ୍"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"ସେଟିଂସ୍"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"କ୍ୟାମେରା"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> ଅନୁବାଦ କରାଯାଇଛି।"</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"ମେସେଜ୍, <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>ରୁ <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>କୁ ଅନୁବାଦ କରାଯାଇଛି।"</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"ପୃଷ୍ଠପଟ କାର୍ଯ୍ୟକଳାପ"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"ଏକ ଆପ ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରୁଛି"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"ଏକ ଆପ ଏବେ ବି ସକ୍ରିୟ ଅଛି"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> ପୃଷ୍ଠପଟରେ ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରୁଛି। ସମୀକ୍ଷା କରିବାକୁ ଟାପ କରନ୍ତୁ।"</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> ବ୍ୟାଟେରୀ ଲାଇଫକୁ ପ୍ରଭାବିତ କରିପାରେ। ସକ୍ରିୟ ଆପ୍ସକୁ ସମୀକ୍ଷା କରିବା ପାଇଁ ଟାପ କରନ୍ତୁ।"</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"ସକ୍ରିୟ ଆପଗୁଡ଼ିକୁ ଯାଞ୍ଚ କରନ୍ତୁ"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"ଆପଣଙ୍କ <xliff:g id="DEVICE">%1$s</xliff:g>ରୁ ଫୋନର କ୍ୟାମେରାକୁ ଆକ୍ସେସ କରାଯାଇପାରିବ ନାହିଁ"</string> diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index d8503aed5e41..c02e01d43105 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -425,9 +425,9 @@ <string name="permdesc_writeCallLog" product="tablet" msgid="2657525794731690397">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ ਦਾ ਕਾਲ ਲੌਗ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਇਨਕਮਿੰਗ ਅਤੇ ਆਊਟਗੋਇੰਗ ਕਾਲਾਂ ਬਾਰੇ ਡਾਟਾ ਸਮੇਤ। ਖਰਾਬ ਐਪਾਂ ਇਸਦੀ ਵਰਤੋਂ ਤੁਹਾਡੇ ਕਾਲ ਲੌਗ ਨੂੰ ਮਿਟਾਉਣ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਲਈ ਕਰ ਸਕਦੀਆਂ ਹਨ।"</string> <string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ Android TV ਡੀਵਾਈਸ ਦਾ ਕਾਲ ਲੌਗ ਸੋਧਣ ਦਿੰਦੀ ਹੈ, ਇਸ ਵਿੱਚ ਇਨਕਮਿੰਗ ਅਤੇ ਆਊਟਗੋਇੰਗ ਕਾਲਾਂ ਬਾਰੇ ਡਾਟਾ ਵੀ ਸ਼ਾਮਲ ਹੈ। ਭੈੜੀਆਂ ਐਪਾਂ ਤੁਹਾਡੀ ਜਾਣਕਾਰੀ ਤੋਂ ਬਿਨਾਂ ਕਾਲ ਲੌਗ ਡਾਟਾ ਮਿਟਾ ਜਾਂ ਸੋਧ ਸਕਦੀਆਂ ਹਨ।"</string> <string name="permdesc_writeCallLog" product="default" msgid="5903033505665134802">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਦਾ ਕਾਲ ਲੌਗ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਇਨਕਮਿੰਗ ਅਤੇ ਆਊਟਗੋਇੰਗ ਕਾਲਾਂ ਬਾਰੇ ਡਾਟਾ ਸਮੇਤ। ਖਰਾਬ ਐਪਾਂ ਇਸਦੀ ਵਰਤੋਂ ਤੁਹਾਡੇ ਕਾਲ ਲੌਗ ਨੂੰ ਮਿਟਾਉਣ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਲਈ ਕਰ ਸਕਦੀਆਂ ਹਨ।"</string> - <string name="permlab_bodySensors" msgid="662918578601619569">"ਵਰਤੋਂ ਵਿੱਚ ਹੋਣ \'ਤੇ ਦਿਲ ਦੀ ਧੜਕਣ ਵਰਗੇ ਸਰੀਰ ਸੰਬੰਧੀ ਸੈਂਸਰ ਤੱਕ ਪਹੁੰਚ ਕਰੋ"</string> + <string name="permlab_bodySensors" msgid="662918578601619569">"ਵਰਤੋਂ ਵਿੱਚ ਹੋਣ \'ਤੇ ਦਿਲ ਦੀ ਧੜਕਣ ਵਰਗੇ ਸਰੀਰ ਸੰਬੰਧੀ ਸੈਂਸਰ ਦੇ ਡਾਟਾ ਤੱਕ ਪਹੁੰਚ ਕਰੋ"</string> <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"ਜਦੋਂ ਐਪ ਵਰਤੋਂ ਵਿੱਚ ਹੋਵੇ, ਤਾਂ ਇਸ ਨਾਲ ਐਪ ਨੂੰ ਦਿਲ ਦੀ ਧੜਕਣ, ਤਾਪਮਾਨ, ਖੂਨ ਵਿੱਚ ਮੌਜੂਦ ਆਕਸੀਜਨ ਦੀ ਫ਼ੀਸਦ ਵਰਗੇ ਸਰੀਰ ਸੰਬੰਧੀ ਸੈਂਸਰ ਦੇ ਡਾਟੇ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਮਿਲਦੀ ਹੈ।"</string> - <string name="permlab_bodySensors_background" msgid="4912560779957760446">"ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲਣ \'ਤੇ ਦਿਲ ਦੀ ਧੜਕਣ ਵਰਗੇ ਸਰੀਰ ਸੰਬੰਧੀ ਸੈਂਸਰ ਤੱਕ ਪਹੁੰਚ ਕਰੋ"</string> + <string name="permlab_bodySensors_background" msgid="4912560779957760446">"ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲਣ \'ਤੇ ਦਿਲ ਦੀ ਧੜਕਣ ਵਰਗੇ ਸਰੀਰ ਸੰਬੰਧੀ ਸੈਂਸਰ ਦੇ ਡਾਟਾ ਤੱਕ ਪਹੁੰਚ ਕਰੋ"</string> <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"ਜਦੋਂ ਐਪ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲ ਰਹੀ ਹੋਵੇ, ਤਾਂ ਇਸ ਨਾਲ ਐਪ ਨੂੰ ਦਿਲ ਦੀ ਧੜਕਣ, ਤਾਪਮਾਨ, ਖੂਨ ਵਿੱਚ ਮੌਜੂਦ ਆਕਸੀਜਨ ਦੀ ਫ਼ੀਸਦ ਵਰਗੇ ਸਰੀਰ ਸੰਬੰਧੀ ਸੈਂਸਰ ਦੇ ਡਾਟੇ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਮਿਲਦੀ ਹੈ।"</string> <string name="permlab_readCalendar" msgid="6408654259475396200">"ਕੈਲੰਡਰ ਵਰਤਾਰਿਆਂ ਅਤੇ ਵੇਰਵਿਆਂ ਨੂੰ ਪੜ੍ਹੋ"</string> <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਸਾਰੇ ਕੈਲੰਡਰ ਇਵੈਂਟਾਂ ਨੂੰ ਪੜ੍ਹ ਸਕਦੀ ਹੈ ਅਤੇ ਤੁਹਾਡੇ ਕੈਲੰਡਰ ਡਾਟੇ ਨੂੰ ਸਾਂਝਾ ਜਾਂ ਰੱਖਿਅਤ ਕਰ ਸਕਦੀ ਹੈ।"</string> @@ -1679,13 +1679,13 @@ <string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"ਚਾਲੂ"</string> <string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"ਬੰਦ"</string> <string name="accessibility_enable_service_title" msgid="3931558336268541484">"ਕੀ <xliff:g id="SERVICE">%1$s</xliff:g> ਨੂੰ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦਾ ਪੂਰਾ ਕੰਟਰੋਲ ਦੇਣਾ ਹੈ?"</string> - <string name="accessibility_service_warning_description" msgid="291674995220940133">"ਪੂਰਾ ਕੰਟਰੋਲ ਉਹਨਾਂ ਐਪਾਂ ਲਈ ਢੁਕਵਾਂ ਹੈ ਜੋ ਪਹੁੰਚਯੋਗਤਾ ਸੰਬੰਧੀ ਲੋੜਾਂ ਵਿੱਚ ਤੁਹਾਡੀ ਮਦਦ ਕਰਦੀਆਂ ਹਨ, ਪਰ ਜ਼ਿਆਦਾਤਰ ਐਪਾਂ ਲਈ ਢੁਕਵਾਂ ਨਹੀਂ ਹੁੰਦਾ।"</string> + <string name="accessibility_service_warning_description" msgid="291674995220940133">"ਪੂਰਾ ਕੰਟਰੋਲ ਉਨ੍ਹਾਂ ਐਪਾਂ ਲਈ ਢੁਕਵਾਂ ਹੈ ਜੋ ਪਹੁੰਚਯੋਗਤਾ ਸੰਬੰਧੀ ਲੋੜਾਂ ਵਿੱਚ ਤੁਹਾਡੀ ਮਦਦ ਕਰਦੀਆਂ ਹਨ, ਪਰ ਜ਼ਿਆਦਾਤਰ ਐਪਾਂ ਲਈ ਢੁਕਵਾਂ ਨਹੀਂ ਹੁੰਦਾ।"</string> <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"ਸਕ੍ਰੀਨ ਨੂੰ ਦੇਖੋ ਅਤੇ ਕੰਟਰੋਲ ਕਰੋ"</string> <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"ਇਹ ਸਕ੍ਰੀਨ \'ਤੇ ਸਾਰੀ ਸਮੱਗਰੀ ਪੜ੍ਹ ਸਕਦੀ ਹੈ ਅਤੇ ਸਮੱਗਰੀ ਨੂੰ ਦੂਜੀਆਂ ਐਪਾਂ ਦੇ ਉੱਪਰ ਦਿਖਾ ਸਕਦੀ ਹੈ।"</string> <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"ਕਾਰਵਾਈਆਂ ਦੇਖੋ ਅਤੇ ਕਰੋ"</string> <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"ਇਹ ਕਿਸੇ ਐਪ ਜਾਂ ਹਾਰਡਵੇਅਰ ਸੈਂਸਰ ਦੇ ਨਾਲ ਤੁਹਾਡੀਆਂ ਅੰਤਰਕਿਰਿਆਵਾਂ ਨੂੰ ਟਰੈਕ ਕਰ ਸਕਦੀ ਹੈ, ਅਤੇ ਤੁਹਾਡੀ ਤਰਫ਼ੋਂ ਐਪਾਂ ਦੇ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰ ਸਕਦੀ ਹੈ।"</string> <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"ਕਰਨ ਦਿਓ"</string> - <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"ਮਨ੍ਹਾਂ ਕਰੋ"</string> + <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"ਨਾ ਕਰਨ ਦਿਓ"</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ਕਿਸੇ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਵਰਤਣਾ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਉਸ \'ਤੇ ਟੈਪ ਕਰੋ:"</string> <string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ਪਹੁੰਚਯੋਗਤਾ ਬਟਨ ਨਾਲ ਵਰਤਣ ਲਈ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਚੁਣੋ"</string> <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"ਅਵਾਜ਼ ਕੁੰਜੀ ਸ਼ਾਰਟਕੱਟ ਨਾਲ ਵਰਤਣ ਲਈ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਚੁਣੋ"</string> @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਐਪ ਇਸ ਵੇਲੇ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"ਇਜਾਜ਼ਤ ਦੀ ਲੋੜ ਹੈ"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"ਕੈਮਰਾ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"ਫ਼ੋਨ \'ਤੇ ਜਾਰੀ ਰੱਖੋ"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਅਣਉਪਲਬਧ ਹੈ"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV ਸੈਟਿੰਗਾਂ ਅਣਉਪਲਬਧ ਹਨ"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"ਟੈਬਲੈੱਟ ਸੈਟਿੰਗਾਂ ਅਣਉਪਲਬਧ ਹਨ"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"ਫ਼ੋਨ ਸੈਟਿੰਗਾਂ ਅਣਉਪਲਬਧ ਹਨ"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"ਤੁਹਾਡੇ <xliff:g id="DEVICE">%1$s</xliff:g> \'ਤੇ ਇਸ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ। ਇਸਦੀ ਬਜਾਏ ਆਪਣੇ Android TV ਡੀਵਾਈਸ \'ਤੇ ਵਰਤ ਕੇ ਦੇਖੋ।"</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"ਤੁਹਾਡੇ <xliff:g id="DEVICE">%1$s</xliff:g> \'ਤੇ ਇਸ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ। ਇਸਦੀ ਬਜਾਏ ਆਪਣੇ ਟੈਬਲੈੱਟ \'ਤੇ ਵਰਤ ਕੇ ਦੇਖੋ।"</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"ਤੁਹਾਡੇ <xliff:g id="DEVICE">%1$s</xliff:g> \'ਤੇ ਇਸ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ। ਇਸਦੀ ਬਜਾਏ ਆਪਣੇ ਫ਼ੋਨ \'ਤੇ ਵਰਤ ਕੇ ਦੇਖੋ।"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"ਇਸ ਸਮੇਂ ਤੁਹਾਡੇ <xliff:g id="DEVICE">%1$s</xliff:g> \'ਤੇ ਇਸ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ। ਇਸਦੀ ਬਜਾਏ ਆਪਣੇ Android TV ਡੀਵਾਈਸ \'ਤੇ ਵਰਤ ਕੇ ਦੇਖੋ।"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"ਇਸ ਸਮੇਂ ਤੁਹਾਡੇ <xliff:g id="DEVICE">%1$s</xliff:g> \'ਤੇ ਇਸ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ। ਇਸਦੀ ਬਜਾਏ ਆਪਣੇ ਟੈਬਲੈੱਟ \'ਤੇ ਵਰਤ ਕੇ ਦੇਖੋ।"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"ਇਸ ਸਮੇਂ ਤੁਹਾਡੇ <xliff:g id="DEVICE">%1$s</xliff:g> \'ਤੇ ਇਸ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ। ਇਸਦੀ ਬਜਾਏ ਆਪਣੇ ਫ਼ੋਨ \'ਤੇ ਵਰਤ ਕੇ ਦੇਖੋ।"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"ਇਹ ਐਪ ਵਧੀਕ ਸੁਰੱਖਿਆ ਦੀ ਬੇਨਤੀ ਕਰ ਰਹੀ ਹੈ। ਇਸਦੀ ਬਜਾਏ ਆਪਣੇ Android TV ਡੀਵਾਈਸ \'ਤੇ ਵਰਤ ਕੇ ਦੇਖੋ।"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"ਇਹ ਐਪ ਵਧੀਕ ਸੁਰੱਖਿਆ ਦੀ ਬੇਨਤੀ ਕਰ ਰਹੀ ਹੈ। ਇਸਦੀ ਬਜਾਏ ਆਪਣੇ ਟੈਬਲੈੱਟ \'ਤੇ ਵਰਤ ਕੇ ਦੇਖੋ।"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"ਇਹ ਐਪ ਵਧੀਕ ਸੁਰੱਖਿਆ ਦੀ ਬੇਨਤੀ ਕਰ ਰਹੀ ਹੈ। ਇਸਦੀ ਬਜਾਏ ਆਪਣੇ ਫ਼ੋਨ \'ਤੇ ਵਰਤ ਕੇ ਦੇਖੋ।"</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ਇਹ ਐਪ Android ਦੇ ਕਿਸੇ ਵਧੇਰੇ ਪੁਰਾਣੇ ਵਰਜਨ ਲਈ ਬਣਾਈ ਗਈ ਸੀ ਅਤੇ ਸ਼ਾਇਦ ਸਹੀ ਢੰਗ ਨਾਲ ਕੰਮ ਨਾ ਕਰੇ। ਅੱਪਡੇਟਾਂ ਲਈ ਜਾਂਚ ਕਰੋ ਜਾਂ ਵਿਕਾਸਕਾਰ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ਅੱਪਡੇਟ ਲਈ ਜਾਂਚ ਕਰੋ"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"ਤੁਹਾਨੂੰ ਨਵੇਂ ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਹੋਏ ਹਨ"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"ਹੋਰ ਜਾਣਨ ਲਈ ਅਤੇ ਬਦਲਾਅ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"\'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਵਿਕਲਪ ਬਦਲ ਗਿਆ ਹੈ"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"ਟੈਪ ਕਰਕੇ ਦੋਖੋ ਕਿ ਕਿਹੜੀਆਂ ਚੀਜ਼ਾਂ ਬਲਾਕ ਕੀਤੀਆਂ ਗਈਆਂ ਹਨ।"</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"ਸੂਚਨਾ ਸੈਟਿੰਗਾਂ ਦੀ ਸਮੀਖਿਆ ਕਰੋ"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13 ਵਿੱਚ, ਤੁਹਾਡੇ ਵੱਲੋਂ ਸਥਾਪਤ ਕੀਤੀਆਂ ਜਾਣ ਵਾਲੀਆਂ ਐਪਾਂ ਨੂੰ ਸੂਚਨਾਵਾਂ ਭੇਜਣ ਲਈ ਤੁਹਾਡੀ ਇਜਾਜ਼ਤ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ। ਮੌਜੂਦਾ ਐਪਾਂ ਲਈ ਇਸ ਇਜਾਜ਼ਤ ਨੂੰ ਬਦਲਣ ਵਾਸਤੇ ਟੈਪ ਕਰੋ।"</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"ਬਾਅਦ ਵਿੱਚ ਯਾਦ ਕਰਵਾਓ"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"ਖਾਰਜ ਕਰੋ"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"ਸਿਸਟਮ"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"ਸੈਟਿੰਗਾਂ"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"ਕੈਮਰਾ"</string> @@ -2090,7 +2071,7 @@ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"ਠੀਕ ਹੈ"</string> <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"ਬੰਦ ਕਰੋ"</string> <string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"ਹੋਰ ਜਾਣੋ"</string> - <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Android 12 ਵਿੱਚ ਵਿਸਤ੍ਰਿਤ ਸੂਚਨਾਵਾਂ ਨੂੰ Android ਅਡੈਪਟਿਵ ਸੂਚਨਾਵਾਂ ਨਾਲ ਬਦਲ ਦਿੱਤਾ ਗਿਆ ਹੈ। ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਕਾਰਵਾਈਆਂ ਅਤੇ ਜਵਾਬਾਂ ਵਾਲੇ ਸੁਝਾਅ ਦਿਖਾਉਂਦੀ ਹੈ ਅਤੇ ਤੁਹਾਡੀਆਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰਦੀ ਹੈ।\n\nਵਿਸਤ੍ਰਿਤ ਸੂਚਨਾਵਾਂ ਸੂਚਨਾ ਸਮੱਗਰੀ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੀਆਂ ਹਨ, ਜਿਸ ਵਿੱਚ ਸੰਪਰਕ ਦੇ ਨਾਮ ਅਤੇ ਸੁਨੇਹੇ ਵਰਗੀ ਨਿੱਜੀ ਜਾਣਕਾਰੀ ਵੀ ਸ਼ਾਮਲ ਹੈ। ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਸੂਚਨਾਵਾਂ ਨੂੰ ਖਾਰਜ ਵੀ ਕਰ ਸਕਦੀ ਹੈ ਜਾਂ ਸੂਚਨਾਵਾਂ ਦਾ ਜਵਾਬ ਵੀ ਦੇ ਸਕਦੀ ਹੈ, ਜਿਵੇਂ ਕਿ ਫ਼ੋਨ ਕਾਲਾਂ ਦਾ ਜਵਾਬ ਦੇਣਾ ਅਤੇ \'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਨੂੰ ਕੰਟਰੋਲ ਕਰਨਾ।"</string> + <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Android 12 ਵਿੱਚ ਵਿਸਤ੍ਰਿਤ ਸੂਚਨਾਵਾਂ ਨੇ Android ਅਡੈਪਟਿਵ ਸੂਚਨਾਵਾਂ ਦੀ ਜਗ੍ਹਾ ਲੈ ਲਈ ਹੈ। ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਕਾਰਵਾਈਆਂ ਅਤੇ ਜਵਾਬਾਂ ਵਾਲੇ ਸੁਝਾਅ ਦਿਖਾਉਂਦੀ ਹੈ ਅਤੇ ਤੁਹਾਡੀਆਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰਦੀ ਹੈ।\n\nਵਿਸਤ੍ਰਿਤ ਸੂਚਨਾਵਾਂ ਸੂਚਨਾ ਸਮੱਗਰੀ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੀਆਂ ਹਨ, ਜਿਸ ਵਿੱਚ ਸੰਪਰਕ ਦੇ ਨਾਮ ਅਤੇ ਸੁਨੇਹੇ ਵਰਗੀ ਨਿੱਜੀ ਜਾਣਕਾਰੀ ਵੀ ਸ਼ਾਮਲ ਹੈ। ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਸੂਚਨਾਵਾਂ ਨੂੰ ਖਾਰਜ ਵੀ ਕਰ ਸਕਦੀ ਹੈ ਜਾਂ ਸੂਚਨਾਵਾਂ ਦਾ ਜਵਾਬ ਵੀ ਦੇ ਸਕਦੀ ਹੈ, ਜਿਵੇਂ ਕਿ ਫ਼ੋਨ ਕਾਲਾਂ ਦਾ ਜਵਾਬ ਦੇਣਾ ਅਤੇ \'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਨੂੰ ਕੰਟਰੋਲ ਕਰਨਾ।"</string> <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ਨਿਯਮਬੱਧ ਮੋਡ ਦੀ ਜਾਣਕਾਰੀ ਵਾਲੀ ਸੂਚਨਾ"</string> <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ਬੈਟਰੀ ਚਾਰਜ ਕਰਨ ਦੇ ਮਿੱਥੇ ਸਮੇਂ ਤੋਂ ਪਹਿਲਾਂ ਸ਼ਾਇਦ ਬੈਟਰੀ ਖਤਮ ਹੋ ਜਾਵੇ"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"ਬੈਟਰੀ ਲਾਈਫ਼ ਵਧਾਉਣ ਲਈ ਬੈਟਰੀ ਸੇਵਰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> ਦਾ ਅਨੁਵਾਦ ਕੀਤਾ ਗਿਆ।"</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"ਸੁਨੇਹੇ ਦਾ <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> ਤੋਂ <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> ਵਿੱਚ ਅਨੁਵਾਦ ਕੀਤਾ ਗਿਆ।"</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"ਬੈਕਗ੍ਰਾਊਂਡ ਸਰਗਰਮੀ"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"ਇੱਕ ਐਪ ਬੈਟਰੀ ਵਰਤ ਰਹੀ ਹੈ"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"ਕੋਈ ਐਪ ਬੈਟਰੀ ਦੀ ਖਪਤ ਕਰ ਰਹੀ ਹੈ"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"ਇੱਕ ਐਪ ਹਾਲੇ ਵੀ ਕਿਰਿਆਸ਼ੀਲ ਹੈ"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> ਵੱਲੋਂ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਬੈਟਰੀ ਵਰਤੀ ਜਾ ਰਹੀ ਹੈ। ਸਮੀਖਿਆ ਲਈ ਟੈਪ ਕਰੋ।"</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲ ਰਹੀ ਹੈ। ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> ਵੱਲੋਂ ਬੈਟਰੀ ਲਾਈਫ਼ ਨੂੰ ਪ੍ਰਭਾਵਿਤ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ। ਕਿਰਿਆਸ਼ੀਲ ਐਪਾਂ ਦੀ ਸਮੀਖਿਆ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"ਕਿਰਿਆਸ਼ੀਲ ਐਪਾਂ ਦੀ ਜਾਂਚ ਕਰੋ"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"ਤੁਹਾਡੇ <xliff:g id="DEVICE">%1$s</xliff:g> ਤੋਂ ਫ਼ੋਨ ਦੇ ਕੈਮਰੇ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ"</string> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 6d9c4b6bfe1f..8e44bde5a4bf 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -1935,36 +1935,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> jest obecnie niedostępna."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> – brak dostępu"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Wymagane są uprawnienia"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Aparat niedostępny"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Kontynuuj na telefonie"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofon niedostępny"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Ustawienia Androida TV są niedostępne"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Ustawienia tabletu są niedostępne"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Ustawienia telefonu są niedostępne"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Z aplikacji nie można skorzystać na urządzeniu <xliff:g id="DEVICE">%1$s</xliff:g>. Użyj urządzenia z Androidem TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Z aplikacji nie można skorzystać na urządzeniu <xliff:g id="DEVICE">%1$s</xliff:g>. Użyj tabletu."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Z aplikacji nie można skorzystać na urządzeniu <xliff:g id="DEVICE">%1$s</xliff:g>. Użyj telefonu."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"W tej chwili na urządzeniu <xliff:g id="DEVICE">%1$s</xliff:g> nie można skorzystać z aplikacji. Użyj urządzenia z Androidem TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"W tej chwili na urządzeniu <xliff:g id="DEVICE">%1$s</xliff:g> nie można skorzystać z aplikacji. Użyj tabletu."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"W tej chwili na urządzeniu <xliff:g id="DEVICE">%1$s</xliff:g> nie można skorzystać z aplikacji. Użyj telefonu."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Ta aplikacja wymaga dodatkowych zabezpieczeń. Użyj urządzenia z Androidem TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Ta aplikacja wymaga dodatkowych zabezpieczeń. Użyj tabletu."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Ta aplikacja wymaga dodatkowych zabezpieczeń. Użyj telefonu."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ta aplikacja jest na starszą wersję Androida i może nie działać prawidłowo. Sprawdź dostępność aktualizacji lub skontaktuj się z programistą."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Sprawdź dostępność aktualizacji"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Masz nowe wiadomości"</string> @@ -2069,14 +2054,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Kliknij, by dowiedzieć się więcej i zmienić ustawienia."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Zmiany w trybie Nie przeszkadzać"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Kliknij, by sprawdzić, co jest zablokowane."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Sprawdź ustawienia powiadomień"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Na Androidzie 13 aplikacje, które zainstalujesz, będą potrzebowały zezwolenia na wysyłanie powiadomień. Kliknij, aby zmienić uprawnienia dla istniejących aplikacji."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Przypomnij później"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Odrzuć"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"System"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Ustawienia"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Aparat"</string> @@ -2295,9 +2276,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Przetłumaczono wiadomość: <xliff:g id="MESSAGE">%1$s</xliff:g>."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Wiadomość przetłumaczono z języka: <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> na język: <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Aktywność w tle"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Aplikacja używa baterii"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Aplikacja jest wciąż aktywna"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"Aplikacja <xliff:g id="APP">%1$s</xliff:g> używa baterii w tle. Kliknij, aby to sprawdzić."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"Aplikacja <xliff:g id="APP">%1$s</xliff:g> może mieć wpływ na czas pracy na baterii. Kliknij, aby sprawdzić aktywne aplikacje."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Sprawdź aktywne aplikacje"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Nie można korzystać z aparatu telefonu na urządzeniu <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index 4c25913cce9a..375e16df61e2 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -768,7 +768,7 @@ <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Apaga os dados sem aviso, redefinindo o sistema de infoentretenimento para a configuração original."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Apaga os dados sem aviso redefinindo o smartphone para a configuração original."</string> <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Apagar dados do perfil"</string> - <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Limpar dados do usuário"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Remover dados do usuário"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Limpa os dados do usuário neste tablet sem aviso prévio."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Limpa os dados do usuário neste dispositivo Android TV sem aviso prévio."</string> <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Apaga os dados do perfil do sistema de infoentretenimento sem aviso."</string> @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> não está disponível no momento."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> indisponível"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Permissão necessária"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Câmera indisponível"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Continuar no smartphone"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Microfone indisponível"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Configurações do Android TV indisponíveis"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Configurações do tablet indisponíveis"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Configurações do smartphone indisponíveis"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Não é possível acessar esse app pelo seu <xliff:g id="DEVICE">%1$s</xliff:g>. Tente pelo dispositivo Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Não é possível acessar esse app pelo seu <xliff:g id="DEVICE">%1$s</xliff:g>. Tente pelo tablet."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Não é possível acessar esse app pelo seu <xliff:g id="DEVICE">%1$s</xliff:g>. Tente pelo smartphone."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"No momento, não é possível acessar esse app pelo seu <xliff:g id="DEVICE">%1$s</xliff:g>. Tente pelo dispositivo Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"No momento, não é possível acessar esse app pelo seu <xliff:g id="DEVICE">%1$s</xliff:g>. Tente pelo tablet."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"No momento, não é possível acessar esse app pelo seu <xliff:g id="DEVICE">%1$s</xliff:g>. Tente pelo smartphone."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Esse app está solicitando segurança extra. Tente pelo dispositivo Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Esse app está solicitando segurança extra. Tente pelo tablet."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Esse app está solicitando segurança extra. Tente pelo smartphone."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Este app foi criado para uma versão mais antiga do Android e pode não funcionar corretamente. Tente verificar se há atualizações ou entre em contato com o desenvolvedor."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Procurar atualizações"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Você tem mensagens novas"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Toque para saber mais e fazer alterações."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"O modo \"Não perturbe\" foi alterado"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Toque para verificar o que está bloqueado."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Revise as configurações de notificação"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"No Android 13, os apps que você instala precisam da sua permissão para enviar notificações. Toque para mudar essa permissão para os apps já instalados."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Lembrar mais tarde"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Dispensar"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Sistema"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Configurações"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Câmera"</string> @@ -2090,7 +2071,7 @@ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string> <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Desativar"</string> <string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Saiba mais"</string> - <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"No Android 12, as notificações avançadas substituíram as notificações adaptáveis. Esse recurso exibe ações e respostas sugeridas, além de organizar suas notificações.\n\nAs notificações avançadas podem acessar o conteúdo das notificações, incluindo informações pessoais como nomes de contatos e mensagens. Elas também podem dispensar ou responder às notificações, como atender chamadas telefônicas e controlar o Não perturbe."</string> + <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"No Android 12, as notificações avançadas substituíram as notificações adaptáveis. Esse recurso mostra ações e respostas sugeridas, além de organizar suas notificações.\n\nAs notificações avançadas podem acessar o conteúdo das notificações, incluindo informações pessoais como nomes de contatos e mensagens. Elas também podem dispensar ou responder às notificações, como atender chamadas telefônicas e controlar o Não perturbe."</string> <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notificação de informação do modo rotina"</string> <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"A bateria pode acabar antes da recarga normal"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"A Economia de bateria foi ativada para aumentar a duração da carga"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Mensagem \"<xliff:g id="MESSAGE">%1$s</xliff:g>\" traduzida."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Mensagem traduzida do <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> para o <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Atividade em segundo plano"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Um app está consumindo bateria"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Um app está descarregando a bateria"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Um app ainda está ativo"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"O app <xliff:g id="APP">%1$s</xliff:g> está consumindo a bateria em segundo plano. Toque para revisar."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"O app <xliff:g id="APP">%1$s</xliff:g> está sendo executado em segundo plano. Toque para gerenciar o uso da bateria."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"O app <xliff:g id="APP">%1$s</xliff:g> pode afetar a duração da bateria. Toque para revisar os apps ativos."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Verificar apps ativos"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Não é possível acessar a câmera do smartphone pelo <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 890851849846..47a6fe521568 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -422,9 +422,9 @@ <string name="permlab_readCallLog" msgid="1739990210293505948">"ler registo de chamadas"</string> <string name="permdesc_readCallLog" msgid="8964770895425873433">"Esta app pode ler o seu histórico de chamadas."</string> <string name="permlab_writeCallLog" msgid="670292975137658895">"escrever registo de chamadas"</string> - <string name="permdesc_writeCallLog" product="tablet" msgid="2657525794731690397">"Permite à app modificar o registo de chamadas do tablet, incluindo os dados sobre as chamadas recebidas e efetuadas. As aplicações maliciosas podem utilizar esta funcionalidade para apagar ou modificar o registo de chamadas."</string> - <string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"Permite à app modificar o registo de chamadas do seu dispositivo Android TV, incluindo os dados sobre as chamadas recebidas e efetuadas. As aplicações maliciosas podem utilizar esta funcionalidade para apagar ou modificar o seu registo de chamadas."</string> - <string name="permdesc_writeCallLog" product="default" msgid="5903033505665134802">"Permite à app modificar o registo de chamadas do telemóvel, incluindo os dados sobre as chamadas recebidas e efetuadas. As aplicações maliciosas podem utilizar esta funcionalidade para apagar ou modificar o seu registo de chamadas."</string> + <string name="permdesc_writeCallLog" product="tablet" msgid="2657525794731690397">"Permite à app modificar o registo de chamadas do tablet, incluindo os dados sobre as chamadas recebidas e efetuadas. As aplicações maliciosas podem usar esta funcionalidade para apagar ou modificar o registo de chamadas."</string> + <string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"Permite à app modificar o registo de chamadas do seu dispositivo Android TV, incluindo os dados sobre as chamadas recebidas e efetuadas. As aplicações maliciosas podem usar esta funcionalidade para apagar ou modificar o seu registo de chamadas."</string> + <string name="permdesc_writeCallLog" product="default" msgid="5903033505665134802">"Permite à app modificar o registo de chamadas do telemóvel, incluindo os dados sobre as chamadas recebidas e efetuadas. As aplicações maliciosas podem usar esta funcionalidade para apagar ou modificar o seu registo de chamadas."</string> <string name="permlab_bodySensors" msgid="662918578601619569">"Aceder a dados de sensores de corpo, como ritmo cardíaco, durante a utilização"</string> <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Permite à app aceder a dados de sensores de corpo, como ritmo cardíaco, temperatura e percentagem de oxigénio no sangue, enquanto está a ser usada."</string> <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Aceder a dados de sensores de corpo, como ritmo cardíaco, quando em seg. plano"</string> @@ -1669,10 +1669,10 @@ <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Aumentar o volume acima do nível recomendado?\n\nOuvir com um volume elevado durante longos períodos poderá ser prejudicial para a sua audição."</string> <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Pretende utilizar o atalho de acessibilidade?"</string> <string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Quando o atalho está ativado, premir ambos os botões de volume durante 3 segundos inicia uma funcionalidade de acessibilidade."</string> - <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Pretende ativar o atalho das funcionalidades de acessibilidade?"</string> + <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Ativar o atalho das funcionalidades de acessibilidade?"</string> <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Manter premidas ambas as teclas de volume durante alguns segundos ativa as funcionalidades de acessibilidade. Estas podem alterar a forma como o seu dispositivo funciona.\n\nFuncionalidades atuais:\n<xliff:g id="SERVICE">%1$s</xliff:g>\npode alterar as funcionalidades selecionadas em Definições > Acessibilidade."</string> <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string> - <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Pretende ativar o atalho do serviço <xliff:g id="SERVICE">%1$s</xliff:g>?"</string> + <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Ativar o atalho do serviço <xliff:g id="SERVICE">%1$s</xliff:g>?"</string> <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Manter premidas ambas as teclas de volume durante alguns segundos ativa o serviço <xliff:g id="SERVICE">%1$s</xliff:g>, uma funcionalidade de acessibilidade. Esta pode alterar a forma como o seu dispositivo funciona.\n\nPode alterar este atalho para outra funcionalidade em Definições > Acessibilidade."</string> <string name="accessibility_shortcut_on" msgid="5463618449556111344">"Ativar"</string> <string name="accessibility_shortcut_off" msgid="3651336255403648739">"Não ativar"</string> @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"De momento, a app <xliff:g id="APP_NAME">%1$s</xliff:g> não está disponível."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> indisponível"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Autorização necessária"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Câmara indisponível"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Continue no telemóvel"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Microfone indisponível"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Definições do Android TV indisponíveis"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Definições do tablet indisponíveis"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Definições do telemóvel indisponíveis"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Não é possível aceder a esta app no seu dispositivo <xliff:g id="DEVICE">%1$s</xliff:g>. Em alternativa, experimente no dispositivo Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Não é possível aceder a esta app no seu dispositivo <xliff:g id="DEVICE">%1$s</xliff:g>. Em alternativa, experimente no tablet."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Não é possível aceder a esta app no seu dispositivo <xliff:g id="DEVICE">%1$s</xliff:g>. Em alternativa, experimente no telemóvel."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"De momento, não é possível aceder a esta app no seu <xliff:g id="DEVICE">%1$s</xliff:g>. Em alternativa, experimente no dispositivo Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"De momento, não é possível aceder a esta app no seu <xliff:g id="DEVICE">%1$s</xliff:g>. Em alternativa, experimente no tablet."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"De momento, não é possível aceder a esta app no seu <xliff:g id="DEVICE">%1$s</xliff:g>. Em alternativa, experimente no telemóvel."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Esta app está a solicitar segurança adicional. Em alternativa, experimente no dispositivo Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Esta app está a solicitar segurança adicional. Em alternativa, experimente no tablet."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Esta app está a solicitar segurança adicional. Em alternativa, experimente no telemóvel."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Esta app foi concebida para uma versão mais antiga do Android e pode não funcionar corretamente. Experimente verificar se existem atualizações ou contacte o programador."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Verificar atualizações"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Tem mensagens novas"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Toque para saber mais e alterar."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"O modo Não incomodar foi alterado"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Toque para verificar o que está bloqueado."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Analise as definições de notificação"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"No Android 13, as apps que instalar precisam da sua autorização para enviar notificações. Toque para alterar esta autorização para as apps existentes."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Lembrar mais tarde"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Ignorar"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Sistema"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Definições"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Câmara"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Mensagem <xliff:g id="MESSAGE">%1$s</xliff:g> traduzida."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Mensagem traduzida de <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> para <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Atividade em segundo plano"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Uma app está a consumir bateria"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Uma app está a consumir rapidamente a bateria"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Uma app ainda está ativa"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"A app <xliff:g id="APP">%1$s</xliff:g> está a consumir bateria em segundo plano. Toque para rever."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"A app <xliff:g id="APP">%1$s</xliff:g> está a ser executada em segundo plano Toque para gerir a utilização da bateria."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"A app <xliff:g id="APP">%1$s</xliff:g> pode afetar a autonomia da bateria. Toque para rever as apps ativas."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Verificar apps ativas"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Não é possível aceder à câmara do telemóvel a partir do dispositivo <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index 4c25913cce9a..375e16df61e2 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -768,7 +768,7 @@ <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Apaga os dados sem aviso, redefinindo o sistema de infoentretenimento para a configuração original."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Apaga os dados sem aviso redefinindo o smartphone para a configuração original."</string> <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Apagar dados do perfil"</string> - <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Limpar dados do usuário"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Remover dados do usuário"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Limpa os dados do usuário neste tablet sem aviso prévio."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Limpa os dados do usuário neste dispositivo Android TV sem aviso prévio."</string> <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Apaga os dados do perfil do sistema de infoentretenimento sem aviso."</string> @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> não está disponível no momento."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> indisponível"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Permissão necessária"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Câmera indisponível"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Continuar no smartphone"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Microfone indisponível"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Configurações do Android TV indisponíveis"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Configurações do tablet indisponíveis"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Configurações do smartphone indisponíveis"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Não é possível acessar esse app pelo seu <xliff:g id="DEVICE">%1$s</xliff:g>. Tente pelo dispositivo Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Não é possível acessar esse app pelo seu <xliff:g id="DEVICE">%1$s</xliff:g>. Tente pelo tablet."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Não é possível acessar esse app pelo seu <xliff:g id="DEVICE">%1$s</xliff:g>. Tente pelo smartphone."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"No momento, não é possível acessar esse app pelo seu <xliff:g id="DEVICE">%1$s</xliff:g>. Tente pelo dispositivo Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"No momento, não é possível acessar esse app pelo seu <xliff:g id="DEVICE">%1$s</xliff:g>. Tente pelo tablet."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"No momento, não é possível acessar esse app pelo seu <xliff:g id="DEVICE">%1$s</xliff:g>. Tente pelo smartphone."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Esse app está solicitando segurança extra. Tente pelo dispositivo Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Esse app está solicitando segurança extra. Tente pelo tablet."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Esse app está solicitando segurança extra. Tente pelo smartphone."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Este app foi criado para uma versão mais antiga do Android e pode não funcionar corretamente. Tente verificar se há atualizações ou entre em contato com o desenvolvedor."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Procurar atualizações"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Você tem mensagens novas"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Toque para saber mais e fazer alterações."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"O modo \"Não perturbe\" foi alterado"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Toque para verificar o que está bloqueado."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Revise as configurações de notificação"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"No Android 13, os apps que você instala precisam da sua permissão para enviar notificações. Toque para mudar essa permissão para os apps já instalados."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Lembrar mais tarde"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Dispensar"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Sistema"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Configurações"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Câmera"</string> @@ -2090,7 +2071,7 @@ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"OK"</string> <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"Desativar"</string> <string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"Saiba mais"</string> - <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"No Android 12, as notificações avançadas substituíram as notificações adaptáveis. Esse recurso exibe ações e respostas sugeridas, além de organizar suas notificações.\n\nAs notificações avançadas podem acessar o conteúdo das notificações, incluindo informações pessoais como nomes de contatos e mensagens. Elas também podem dispensar ou responder às notificações, como atender chamadas telefônicas e controlar o Não perturbe."</string> + <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"No Android 12, as notificações avançadas substituíram as notificações adaptáveis. Esse recurso mostra ações e respostas sugeridas, além de organizar suas notificações.\n\nAs notificações avançadas podem acessar o conteúdo das notificações, incluindo informações pessoais como nomes de contatos e mensagens. Elas também podem dispensar ou responder às notificações, como atender chamadas telefônicas e controlar o Não perturbe."</string> <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Notificação de informação do modo rotina"</string> <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"A bateria pode acabar antes da recarga normal"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"A Economia de bateria foi ativada para aumentar a duração da carga"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Mensagem \"<xliff:g id="MESSAGE">%1$s</xliff:g>\" traduzida."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Mensagem traduzida do <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> para o <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Atividade em segundo plano"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Um app está consumindo bateria"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Um app está descarregando a bateria"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Um app ainda está ativo"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"O app <xliff:g id="APP">%1$s</xliff:g> está consumindo a bateria em segundo plano. Toque para revisar."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"O app <xliff:g id="APP">%1$s</xliff:g> está sendo executado em segundo plano. Toque para gerenciar o uso da bateria."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"O app <xliff:g id="APP">%1$s</xliff:g> pode afetar a duração da bateria. Toque para revisar os apps ativos."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Verificar apps ativos"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Não é possível acessar a câmera do smartphone pelo <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index a4ecb25ea270..5b84189231e8 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -1934,36 +1934,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> nu este disponibilă momentan."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> nu este disponibilă"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Necesită permisiune"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Camera video nu este disponibilă"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Continuați pe telefon"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Microfon indisponibil"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Setările pentru Android TV sunt indisponibile"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Setările pentru tabletă sunt indisponibile"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Setările pentru telefon sunt indisponibile"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Aplicația nu se poate accesa pe <xliff:g id="DEVICE">%1$s</xliff:g>. Încercați pe dispozitivul Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Aplicația nu se poate accesa pe <xliff:g id="DEVICE">%1$s</xliff:g>. Încercați pe tabletă."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Aplicația nu se poate accesa pe <xliff:g id="DEVICE">%1$s</xliff:g>. Încercați pe telefon."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Aplicația nu poate fi accesată pe <xliff:g id="DEVICE">%1$s</xliff:g> momentan. Încercați pe dispozitivul Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Aplicația nu poate fi accesată pe <xliff:g id="DEVICE">%1$s</xliff:g> momentan. Încercați pe tabletă."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Aplicația nu poate fi accesată pe <xliff:g id="DEVICE">%1$s</xliff:g> momentan. Încercați pe telefon."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Aplicația necesită securitate suplimentară. Încercați pe dispozitivul Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Aplicația necesită securitate suplimentară. Încercați pe tabletă."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Aplicația necesită securitate suplimentară. Încercați pe telefon."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Această aplicație a fost creată pentru o versiune Android mai veche și este posibil să nu funcționeze corect. Încercați să căutați actualizări sau contactați dezvoltatorul."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Căutați actualizări"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Aveți mesaje noi"</string> @@ -2068,14 +2053,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Atingeți ca să aflați mai multe și să modificați"</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Funcția Nu deranja s-a schimbat"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Atingeți pentru a verifica ce este blocat."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Examinați setările pentru notificări"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Pe Android 13, aplicațiile pe care le instalați necesită permisiunea de a trimite notificări. Atingeți ca să modificați permisiunea pentru aplicațiile existente."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Mai târziu"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Închideți"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Sistem"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Setări"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Cameră foto"</string> @@ -2294,9 +2275,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> a fost tradus."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Mesaj tradus din <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> în <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Activitate de fundal"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"O aplicație folosește bateria"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"O aplicație consumă bateria"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"O aplicație este încă activă"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> folosește bateria în fundal. Atingeți pentru a examina."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> rulează în fundal. Atingeți pentru a gestiona utilizarea bateriei."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> poate afecta autonomia bateriei. Atingeți pentru a examina aplicațiile active."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Verificați aplicațiile active"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Nu se poate accesa camera foto a telefonului de pe <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 7c6b04365451..b90c3c3cc87a 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -1935,36 +1935,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" сейчас недоступно."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"Недоступно: <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Требуется разрешение"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Камера недоступна"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Продолжите на телефоне"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Микрофон недоступен"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Настройки Android TV недоступны"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Настройки планшета недоступны"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Настройки телефона недоступны"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Эта функция недоступна на устройстве <xliff:g id="DEVICE">%1$s</xliff:g>. Используйте Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Эта функция недоступна на устройстве <xliff:g id="DEVICE">%1$s</xliff:g>. Используйте планшет."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Эта функция недоступна на устройстве <xliff:g id="DEVICE">%1$s</xliff:g>. Используйте телефон."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Эта функция пока недоступна на устройстве <xliff:g id="DEVICE">%1$s</xliff:g>. Используйте Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Эта функция пока недоступна на устройстве <xliff:g id="DEVICE">%1$s</xliff:g>. Используйте планшет."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Эта функция пока недоступна на устройстве <xliff:g id="DEVICE">%1$s</xliff:g>. Используйте телефон."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Это приложение запрашивает дополнительные меры защиты. Используйте Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Это приложение запрашивает дополнительные меры защиты. Используйте планшет."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Это приложение запрашивает дополнительные меры защиты. Используйте телефон."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Это приложение было создано для более ранней версии Android и может работать со сбоями. Проверьте наличие обновлений или свяжитесь с разработчиком."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Проверить обновления"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Новые сообщения"</string> @@ -2009,7 +1994,7 @@ <string name="autofill_picker_no_suggestions" msgid="1076022650427481509">"Нет вариантов автозаполнения"</string> <string name="autofill_picker_some_suggestions" msgid="5560549696296202701">"{count,plural, =1{1 вариант автозаполнения}one{# вариант автозаполнения}few{# варианта автозаполнения}many{# вариантов автозаполнения}other{# варианта автозаполнения}}"</string> <string name="autofill_save_title" msgid="7719802414283739775">"Сохранить в сервисе "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string> - <string name="autofill_save_title_with_type" msgid="3002460014579799605">"Сохранить данные (<xliff:g id="TYPE">%1$s</xliff:g>) в сервисе "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string> + <string name="autofill_save_title_with_type" msgid="3002460014579799605">"Сохран. данные (<xliff:g id="TYPE">%1$s</xliff:g>) в сервисе "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string> <string name="autofill_save_title_with_2types" msgid="3783270967447869241">"Сохранить данные (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>) в сервисе "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string> <string name="autofill_save_title_with_3types" msgid="6598228952100102578">"Сохранить данные (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>) в сервисе "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string> <string name="autofill_update_title" msgid="3630695947047069136">"Обновить в сервисе "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string> @@ -2069,14 +2054,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Нажмите, чтобы узнать больше и изменить настройки."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Настройки режима \"Не беспокоить\" изменены"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Нажмите, чтобы проверить настройки."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Проверьте настройки уведомлений"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Если вы хотите получать уведомления от приложения в Android 13, после установки ему нужно предоставить надлежащее разрешение. Нажмите, чтобы настроить разрешения для установленных приложений."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Напомнить позже"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Закрыть"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Система"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Настройки"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Камера"</string> @@ -2295,9 +2276,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Сообщение \"<xliff:g id="MESSAGE">%1$s</xliff:g>\" переведено."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Сообщение переведено на <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>. Язык оригинала: <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Работа в фоновом режиме"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Приложение расходует заряд батареи"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Одно из приложений быстро расходует заряд батареи"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Приложение все ещё активно"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"Приложение \"<xliff:g id="APP">%1$s</xliff:g>\" расходует заряд батареи в фоновом режиме. Нажмите, чтобы узнать подробности."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"\"<xliff:g id="APP">%1$s</xliff:g>\" работает в фоновом режиме. Нажмите, чтобы изменить настройки, связанные с расходом заряда батареи."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"Приложение \"<xliff:g id="APP">%1$s</xliff:g>\" может влиять на время работы батареи. Нажмите, чтобы увидеть активные приложения."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Проверить активные приложения"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"У устройства \"<xliff:g id="DEVICE">%1$s</xliff:g>\" нет доступа к камере телефона."</string> diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml index 37223e9dc46d..1cb81a98f39d 100644 --- a/core/res/res/values-si/strings.xml +++ b/core/res/res/values-si/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> මේ දැන් ලබා ගත නොහැකිය."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> නොතිබේ"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"අවසරය අවශ්යයි"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"කැමරාව ලබා ගත නොහැකිය"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"දුරකථනයෙන් දිගටම කර ගෙන යන්න"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"මයික්රෆෝනය ලබා ගත නොහැකිය"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV සැකසීම් ලබා ගත නොහැකිය"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"ටැබ්ලට් සැකසීම් ලබා ගත නොහැකිය"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"දුරකථන සැකසීම් ලබා ගත නොහැකිය"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"මෙයට ඔබගේ <xliff:g id="DEVICE">%1$s</xliff:g> හිදී ප්රවේශ විය නොහැකිය. ඒ වෙනුවට ඔබගේ Android TV උපාංගයෙහි උත්සාහ කරන්න."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"මෙයට ඔබගේ <xliff:g id="DEVICE">%1$s</xliff:g> හිදී ප්රවේශ විය නොහැකිය. ඒ වෙනුවට ඔබගේ ටැබ්ලටයෙහි උත්සාහ කරන්න."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"මෙයට ඔබගේ <xliff:g id="DEVICE">%1$s</xliff:g> හිදී ප්රවේශ විය නොහැකිය. ඒ වෙනුවට ඔබගේ දුරකථනයෙහි උත්සාහ කරන්න."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"මේ අවස්ථාවේදී මෙයට ඔබගේ <xliff:g id="DEVICE">%1$s</xliff:g> හිදී ප්රවේශ විය නොහැකිය. ඒ වෙනුවට ඔබගේ Android TV උපාංගයෙහි උත්සාහ කරන්න."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"මේ අවස්ථාවේදී මෙයට ඔබගේ <xliff:g id="DEVICE">%1$s</xliff:g> හිදී ප්රවේශ විය නොහැකිය. ඒ වෙනුවට ඔබගේ ටැබ්ලටයෙහි උත්සාහ කරන්න."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"මේ අවස්ථාවේදී මෙයට ඔබගේ <xliff:g id="DEVICE">%1$s</xliff:g> හිදී ප්රවේශ විය නොහැකිය. ඒ වෙනුවට ඔබගේ දුරකථනයෙහි උත්සාහ කරන්න."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"මෙම යෙදුම අමතර ආරක්ෂාවක් ඉල්ලා සිටී. ඒ වෙනුවට ඔබගේ Android TV උපාංගයෙහි උත්සාහ කරන්න."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"මෙම යෙදුම අමතර ආරක්ෂාවක් ඉල්ලා සිටී. ඒ වෙනුවට ඔබගේ ටැබ්ලටයෙහි උත්සාහ කරන්න."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"මෙම යෙදුම අමතර ආරක්ෂාවක් ඉල්ලා සිටී. ඒ වෙනුවට ඔබගේ දුරකථනයෙහි උත්සාහ කරන්න."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"මෙම යෙදුම Android හි පැරණි අනුවාදයක් සඳහා තනා ඇති අතර නිසියාකාරව ක්රියා නොකරනු ඇත. යාවත්කාලීන සඳහා පරික්ෂා කිරීම උත්සාහ කරන්න, නැතහොත් සංවර්ධක අමතන්න."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"යාවත්කාලීන සඳහා පරික්ෂා කරන්න"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"ඔබට නව පණිවිඩ තිබේ"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"තව දැන ගැනීමට සහ වෙනස් කිරීමට තට්ටු කරන්න."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"බාධා නොකරන්න වෙනස් කර ඇත"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"අවහිර කර ඇති දේ පරීක්ෂා කිරීමට තට්ටු කරන්න."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"දැනුම්දීම් සැකසීම් සමාලෝචනය කරන්න"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13 හි, ඔබ ස්ථාපනය කරන යෙදුම්වලට දැනුම්දීම් යැවීමට ඔබගේ අවසරය අවශ්ය වේ. තිබෙන යෙදුම් සඳහා මෙම අවසරය වෙනස් කිරීමට තට්ටු කරන්න."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"මට පසුව මතක් කරන්න"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"ඉවත ලන්න"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"පද්ධතිය"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"සැකසීම්"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"කැමරාව"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> පරිවර්තනය කරන ලදි."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"පණිවිඩය <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> සිට <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> භාෂාවට පරිවර්තනය කරන ලදි."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"පසුබිම් ක්රියාකාරකම"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"යෙදුමක් බැටරිය භාවිත කරමින් ඇත"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"යෙදුමක් බැටරිය බැස යාමට හේතු වේ"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"යෙදුමක් තවම සක්රියයි"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> පසුබිමේ බැටරිය භාවිත කරමින් ඇත. සමාලෝචනය කිරීමට තට්ටු කරන්න."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> පසුබිමින් ධාවනය වෙමින් පවතී. බැටරි භාවිතය කළමනාකරණය කිරීමට තට්ටු කරන්න."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> බැටරි ආයු කාලය සඳහා බලපෑමට ඉඩ ඇත. සක්රිය යෙදුම් සමාලෝචනය කිරීමට තට්ටු කරන්න."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"සක්රිය යෙදුම් පරීක්ෂා කරන්න"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"ඔබගේ <xliff:g id="DEVICE">%1$s</xliff:g> වෙතින් දුරකථනයේ කැමරාවට ප්රවේශ විය නොහැකිය"</string> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index b9edd9aad115..70f6a51a7043 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -1699,7 +1699,7 @@ <string name="color_inversion_feature_name" msgid="326050048927789012">"Inverzia farieb"</string> <string name="color_correction_feature_name" msgid="3655077237805422597">"Úprava farieb"</string> <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Režim jednej ruky"</string> - <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Veľmi tmavé"</string> + <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Mimoriadne stmavenie"</string> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Pridržali ste tlačidlá hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je zapnutá."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Pridržali ste tlačidlá hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je vypnutá."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Ak chcete používať službu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, pridržte tri sekundy oba klávesy hlasitosti"</string> @@ -1935,36 +1935,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> nie je teraz dostupná."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> nie je k dispozícii"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Vyžaduje sa povolenie"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kamera nie je k dispozícii"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Pokračujte v telefóne"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofón nie je k dispozícii"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Nastavenia zariadenia Android TV nie sú k dispozícii"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Nastavenia tabletu nie sú k dispozícii"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Nastavenia telefónu nie sú k dispozícii"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"V zariadení <xliff:g id="DEVICE">%1$s</xliff:g> momentálne nemáte prístup k tomuto obsahu. Skúste namiesto toho použiť zariadenie Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"V zariadení <xliff:g id="DEVICE">%1$s</xliff:g> momentálne nemáte prístup k tomuto obsahu. Skúste namiesto toho použiť tablet."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"V zariadení <xliff:g id="DEVICE">%1$s</xliff:g> momentálne nemáte prístup k tomuto obsahu. Skúste namiesto toho použiť telefón."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"V zariadení <xliff:g id="DEVICE">%1$s</xliff:g> momentálne nemáte prístup k tomuto obsahu. Skúste namiesto toho použiť zariadenie Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"V zariadení <xliff:g id="DEVICE">%1$s</xliff:g> momentálne nemáte prístup k tomuto obsahu. Skúste namiesto toho použiť tablet."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"V zariadení <xliff:g id="DEVICE">%1$s</xliff:g> momentálne nemáte prístup k tomuto obsahu. Skúste namiesto toho použiť telefón."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Táto aplikácia požaduje dodatočné zabezpečenie. Skúste namiesto toho použiť zariadenie Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Táto aplikácia požaduje dodatočné zabezpečenie. Skúste namiesto toho použiť tablet."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Táto aplikácia požaduje dodatočné zabezpečenie. Skúste namiesto toho použiť telefón."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Táto aplikácia bola zostavená pre staršiu verziu Androidu a nemusí správne fungovať. Skúste skontrolovať dostupnosť aktualizácií alebo kontaktovať vývojára."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Skontrolovať dostupnosť aktualizácie"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Máte nové správy."</string> @@ -2069,14 +2054,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Klepnutím získate ďalšie informácie a budete môcť vykonať zmeny."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Režim bez vyrušení sa zmenil"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Klepnutím skontrolujete, čo je blokované."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Kontrola nastavení upozornení"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"V Androide 13 vyžadujú nainštalované aplikácie povolenie, aby mohli odosielať upozornenia. Klepnutím môžete zmeniť toto povolenie pre existujúce aplikácie."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Pripomenúť neskôr"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Zavrieť"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Systém"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Nastavenia"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Fotoaparát"</string> @@ -2295,9 +2276,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Správa <xliff:g id="MESSAGE">%1$s</xliff:g> bola preložená."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Správa bola preložená z jazyka <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> do jazyka <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Aktivita na pozadí"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Aplikácia používa batériu"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Nejaká aplikácia vybíja batériu"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Aplikácia je stále aktívna"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> používa batériu na pozadí. Skontrolujte to klepnutím."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"Aplikácia <xliff:g id="APP">%1$s</xliff:g> je spustená na pozadí. Kepnutím spravujte spotrebu batérie."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> môže mať vplyv na výdrž batérie. Klepnutím si zobrazte aktívne aplikácie."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Skontrolovať aktívne aplikácie"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"V zariadení <xliff:g id="DEVICE">%1$s</xliff:g> nemáte prístup ku kamere telefónu"</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index f7020aec0d50..7515456765cc 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -1935,36 +1935,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutno ni na voljo."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"»<xliff:g id="ACTIVITY">%1$s</xliff:g>« ni na voljo"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Potrebno je dovoljenje"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Fotoaparat ni na voljo"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Nadaljevanje v telefonu"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofon ni na voljo"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Nastavitve naprave Android TV niso na voljo"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Nastavitve tabličnega računalnika niso na voljo"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Nastavitve telefona niso na voljo"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"V napravi <xliff:g id="DEVICE">%1$s</xliff:g> ni mogoče dostopati do te vsebine. Poskusite z napravo Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"V napravi <xliff:g id="DEVICE">%1$s</xliff:g> ni mogoče dostopati do te vsebine. Poskusite s tabličnim računalnikom."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"V napravi <xliff:g id="DEVICE">%1$s</xliff:g> ni mogoče dostopati do te vsebine. Poskusite s telefonom."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"V napravi <xliff:g id="DEVICE">%1$s</xliff:g> trenutno ni mogoče dostopati do te vsebine. Poskusite z napravo Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"V napravi <xliff:g id="DEVICE">%1$s</xliff:g> trenutno ni mogoče dostopati do te vsebine. Poskusite s tabličnim računalnikom."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"V napravi <xliff:g id="DEVICE">%1$s</xliff:g> trenutno ni mogoče dostopati do te vsebine. Poskusite s telefonom."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Ta aplikacija zahteva dodatno varnost. Poskusite z napravo Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Ta aplikacija zahteva dodatno varnost. Poskusite s tabličnim računalnikom."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Ta aplikacija zahteva dodatno varnost. Poskusite s telefonom."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ta aplikacija je bila zasnovana za starejšo različico Androida in morda ne bo delovala pravilno. Preverite, ali so na voljo posodobitve, ali pa se obrnite na razvijalca."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Preveri, ali je na voljo posodobitev"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Imate nova sporočila."</string> @@ -2069,14 +2054,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Dotaknite se, če želite izvedeti več in spremeniti."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Način »ne moti« je spremenjen"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Dotaknite se, da preverite, kaj je blokirano."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Preglejte nastavitve obvestil"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"V Androidu 13 bodo aplikacije, ki jih namestite, za pošiljanje obvestil potrebovale vaše dovoljenje. Dotaknite se, če želite spremeniti to dovoljenje za obstoječe aplikacije."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Opomni me pozneje"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Opusti"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Sistem"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Nastavitve"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Fotoaparat"</string> @@ -2295,9 +2276,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Sporočilo »<xliff:g id="MESSAGE">%1$s</xliff:g>« je prevedeno."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Sporočilo je prevedeno iz jezika »<xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>« v jezik »<xliff:g id="TO_LANGUAGE">%2$s</xliff:g>«."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Dejavnost v ozadju"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Aplikacija porablja energijo baterije"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Energijsko potratna aplikacija"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Aplikacija je še vedno aktivna"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> porablja energijo baterije v ozadju. Dotaknite se za pregled."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> se izvaja v ozadju. Za upravljanje porabe energije baterije se dotaknite."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> morda vpliva na čas delovanja baterije. Dotaknite se za pregled aktivnih aplikacij."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Preverite aktivne aplikacije"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Ni mogoče dostopati do fotoaparata telefona prek naprave <xliff:g id="DEVICE">%1$s</xliff:g>."</string> diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml index 9d4cd999f588..f247fa9fb7b1 100644 --- a/core/res/res/values-sq/strings.xml +++ b/core/res/res/values-sq/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> nuk ofrohet për momentin."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> nuk ofrohet"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Kërkohet leje"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kamera nuk ofrohet"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Vazhdo në telefon"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofoni nuk ofrohet"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Cilësimet e Android TV nuk ofrohen"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Cilësimet e tabletit nuk ofrohen"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Cilësimet e telefonit nuk ofrohen"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Qasja është e pamundur në <xliff:g id="DEVICE">%1$s</xliff:g>. Provoje në pajisjen Android TV më mirë."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Qasja është e pamundur në <xliff:g id="DEVICE">%1$s</xliff:g>. Provoje në tablet më mirë."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Qasja është e pamundur në <xliff:g id="DEVICE">%1$s</xliff:g>. Provoje në telefon më mirë."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Qasja është e pamundur në <xliff:g id="DEVICE">%1$s</xliff:g> për momentin. Provoje në pajisjen Android TV më mirë."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Qasja është e pamundur në <xliff:g id="DEVICE">%1$s</xliff:g> për momentin. Provoje në tablet më mirë."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Qasja është e pamundur në <xliff:g id="DEVICE">%1$s</xliff:g> për momentin. Provoje në telefon më mirë."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Ky aplikacion po kërkon siguri shtesë. Provoje në pajisjen Android TV më mirë."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Ky aplikacion po kërkon siguri shtesë. Provoje në tablet më mirë."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Ky aplikacion po kërkon siguri shtesë. Provoje në telefon më mirë."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ky aplikacion është ndërtuar për një version më të vjetër të Android dhe mund të mos funksionojë mirë. Provo të kontrollosh për përditësime ose kontakto me zhvilluesin."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Kontrollo për përditësim"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Ke mesazhe të reja"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Trokit për të mësuar më shumë dhe për të ndryshuar."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"\"Mos shqetëso\" ka ndryshuar"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Trokit për të shënuar atë që është bllokuar"</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Rishiko cilësimet e njoftimeve"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Në Android 13, aplikacionet që instalon kanë nevojë për lejen tënde për të dërguar njoftime. Trokit për ta ndryshuar këtë leje për aplikacionet ekzistuese."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Më kujto më vonë"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Hiq"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Sistemi"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Cilësimet"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Kamera"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> i përkthyer."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Mesazhi u përkthye nga <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> në <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Aktiviteti në sfond"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Një aplikacion po përdor baterinë"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Një aplikacion është ende aktiv"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> po përdor baterinë në sfond. Trokit për ta rishikuar."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> mund të kenë ndikim në kohëzgjatjen e baterisë. Trokit për të rishikuar aplikacionet aktive."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Kontrollo aplikacionet aktive"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Nuk mund të qasesh në kamerën e telefonit tënd nga <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index fa4cafb5b28b..3a5db52eab52 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -1934,36 +1934,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"Апликација <xliff:g id="APP_NAME">%1$s</xliff:g> тренутно није доступна."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> – није доступно"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Потребна је дозвола"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Камера није доступна"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Наставите на телефону"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Микрофон је недоступан"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Подешавања Android TV-а су недоступна"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Подешавања таблета су недоступна"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Подешавања телефона су недоступна"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Овој апликацији не може да се приступи са уређаја <xliff:g id="DEVICE">%1$s</xliff:g>. Пробајте на Android TV уређају."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Овој апликацији не може да се приступи са уређаја <xliff:g id="DEVICE">%1$s</xliff:g>. Пробајте на таблету."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Овој апликацији не може да се приступи са уређаја <xliff:g id="DEVICE">%1$s</xliff:g>. Пробајте на телефону."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Овој апликацији тренутно не може да се приступи са уређаја <xliff:g id="DEVICE">%1$s</xliff:g>. Пробајте на Android TV уређају."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Овој апликацији тренутно не може да се приступи са уређаја <xliff:g id="DEVICE">%1$s</xliff:g>. Пробајте на таблету."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Овој апликацији тренутно не може да се приступи са уређаја <xliff:g id="DEVICE">%1$s</xliff:g>. Пробајте на телефону."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Ова апликација захтева додатну безбедност. Пробајте на Android TV уређају."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Ова апликација захтева додатну безбедност. Пробајте на таблету."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Ова апликација захтева додатну безбедност. Пробајте на телефону."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ова апликација је направљена за старију верзију Android-а, па можда неће радити исправно. Потражите ажурирања или контактирајте програмера."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Потражи ажурирање"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Имате нове поруке"</string> @@ -2068,14 +2053,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Додирните да бисте сазнали више и променили подешавање."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Режим Не узнемиравај је промењен"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Додирните да бисте проверили шта је блокирано."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Прегледајте подешавања обавештења"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"У Android-у 13 апликације које инсталирате морају да имају дозволу за слање обавештења. Додирните да бисте променили ову дозволу за постојеће апликације."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Подсети ме касније"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Одбаци"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Систем"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Подешавања"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Камера"</string> @@ -2294,9 +2275,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> Преведено."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Порука је преведена са језика <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> на <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Активност у позадини"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Апликација користи батерију"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Апликација вам празни батерију"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Апликација је и даље активна"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> користи батерију у позадини. Додирните да бисте прегледали."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"Апликација <xliff:g id="APP">%1$s</xliff:g> ради у позадини. Додирните да бисте управљали потрошњом батерије."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> може да утиче на трајање батерије. Додирните да бисте прегледали активне апликације."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Проверите активне апликације"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Не може да се приступи камери телефона са <xliff:g id="DEVICE">%1$s</xliff:g> уређаја"</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index 13b1fcd2e5f6..5cf929f9d399 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> är inte tillgängligt just nu."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> är inte tillgänglig"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Behörighet krävs"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kameran är inte tillgänglig"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Fortsätt på telefonen"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofonen är inte tillgänglig"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Inställningarna för Android TV är inte tillgängliga"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Surfplattans inställningar är inte tillgängliga"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Telefonens inställningar är inte tillgängliga"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Det går inte att streama detta till <xliff:g id="DEVICE">%1$s</xliff:g>. Testa med Android TV-enheten i stället."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Det går inte att streama detta till <xliff:g id="DEVICE">%1$s</xliff:g>. Testa med surfplattan i stället."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Det går inte att streama detta till <xliff:g id="DEVICE">%1$s</xliff:g>. Testa med telefonen i stället."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Det går inte att streama detta till <xliff:g id="DEVICE">%1$s</xliff:g> för närvarande. Testa med Android TV-enheten i stället."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Det går inte att streama detta till <xliff:g id="DEVICE">%1$s</xliff:g> för närvarande. Testa med surfplattan i stället."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Det går inte att streama detta till <xliff:g id="DEVICE">%1$s</xliff:g> för närvarande. Testa med telefonen i stället."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Appen begär ytterligare säkerhet. Testa med Android TV-enheten i stället."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Appen begär ytterligare säkerhet. Testa med surfplattan i stället."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Appen begär ytterligare säkerhet. Testa med telefonen i stället."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Appen har utvecklats för en äldre version av Android och kanske inte fungerar som den ska. Testa att söka efter uppdateringar eller kontakta utvecklaren."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Sök efter uppdateringar"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Du har nya meddelanden"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Tryck här om du vill läsa mer och ändra inställningarna."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Stör ej har ändrats"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Tryck om du vill se vad som blockeras."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Granska aviseringsinställningarna"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"I Android 13 behöver appar som du installerar behörighet att skicka aviseringar. Tryck om du vill ändra denna behörighet för befintliga appar."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Påminn mig senare"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Stäng"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"System"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Inställningar"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Kamera"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> har översatts."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Meddelandet har översatts från <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> till<xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Bakgrundsaktivitet"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"En app använder batteriet"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"En app är fortfarande aktiv"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> använder batteriet i bakgrunden. Tryck för att granska."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> kan påverka batteritiden. Tryck för att granska de aktiva apparna."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Kontrollera aktiva appar"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Telefonens kamera kan inte användas från <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index 031fad56e1fb..cf7044532e45 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> haipatikani hivi sasa."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> haipatikani"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Ruhusa inahitajika"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kamera haipatikani"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Endelea kwenye simu"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Maikrofoni haipatikani"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Mipangilio ya Android TV haipatikani"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Mipangilio ya kompyuta kibao haipatikani"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Mipangilio ya simu haipatikani"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Huwezi kufikia programu hii kwenye <xliff:g id="DEVICE">%1$s</xliff:g> chako. Badala yake jaribu kwenye kifaa chako cha Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Huwezi kufikia programu hii kwenye <xliff:g id="DEVICE">%1$s</xliff:g> chako. Badala yake jaribu kwenye kompyuta yako kibao."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Huwezi kufikia programu hii kwenye <xliff:g id="DEVICE">%1$s</xliff:g> chako. Badala yake jaribu kwenye simu yako."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Huwezi kufikia programu hii kwenye <xliff:g id="DEVICE">%1$s</xliff:g> chako kwa muda huu. Badala yake jaribu kwenye kifaa chako cha Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Huwezi kufikia programu hii kwenye <xliff:g id="DEVICE">%1$s</xliff:g> chako kwa muda huu. Badala yake jaribu kwenye kompyuta yako kibao."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Huwezi kufikia programu hii kwenye <xliff:g id="DEVICE">%1$s</xliff:g> chako kwa muda huu. Badala yake jaribu kwenye simu yako."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Programu hii inaomba usalama wa ziada. Badala yake jaribu kwenye kifaa chako cha Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Programu hii inaomba usalama wa ziada. Badala yake jaribu kwenye kompyuta yako kibao."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Programu hii inaomba usalama wa ziada. Badala yake jaribu kwenye simu yako."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Programu hii iliundwa kwa ajili ya toleo la zamani la Android na huenda isifanye kazi vizuri. Jaribu kuangalia masasisho au uwasiliane na msanidi programu."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Angalia masasisho"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Una ujumbe mpya"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Gusa ili upate maelezo zaidi na ubadilishe."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Kipengele cha Usinisumbue kimebadilishwa"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Gusa ili uangalie kipengee ambacho kimezuiwa."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Kagua mipangilio ya arifa"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Kwenye Android toleo la 13, programu ambazo unasakinisha zitahitaji ruhusa yako ili zikutumie arifa. Gusa ili ubadilishe ruhusa hii kwa programu zilizopo."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Nikumbushe baadaye"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Ondoa"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Mfumo"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Mipangilio"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Kamera"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> Imetafsiriwa."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Ujumbe umetafsiriwa kwa <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> kutoka <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Shughuli za Chinichini"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Programu inatumia betri"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Programu bado inatumika"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> inatumia betri chinichini. Gusa ili ukague."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> inaweza kuathiri muda wa matumizi ya betri. Gusa ili ukague programu zinazotumika."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Angalia programu zinazotumika"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Haiwezi kufikia kamera ya simu kutoka kwenye <xliff:g id="DEVICE">%1$s</xliff:g> yako"</string> diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml index 4ddfccba0bb6..31d702942b64 100644 --- a/core/res/res/values-ta/strings.xml +++ b/core/res/res/values-ta/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸ் இப்போது கிடைப்பதில்லை."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> இல்லை"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"அனுமதி தேவை"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"கேமராவைப் பயன்படுத்த முடியாது"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"மொபைலில் தொடருங்கள்"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"மைக்ரோஃபோனைப் பயன்படுத்த முடியாது"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV அமைப்புகளைப் பயன்படுத்த முடியாது"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"டேப்லெட் அமைப்புகளைப் பயன்படுத்த முடியாது"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"மொபைல் அமைப்புகளைப் பயன்படுத்த முடியாது"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"உங்கள் <xliff:g id="DEVICE">%1$s</xliff:g> சாதனத்தில் இதை அணுக முடியாது. அதற்குப் பதிலாக உங்கள் Android TV சாதனத்தில் பயன்படுத்திப் பார்க்கவும்."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"உங்கள் <xliff:g id="DEVICE">%1$s</xliff:g> சாதனத்தில் இதை அணுக முடியாது. அதற்குப் பதிலாக உங்கள் டேப்லெட்டில் பயன்படுத்திப் பார்க்கவும்."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"உங்கள் <xliff:g id="DEVICE">%1$s</xliff:g> சாதனத்தில் இதை அணுக முடியாது. அதற்குப் பதிலாக உங்கள் மொபைலில் பயன்படுத்திப் பார்க்கவும்."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"தற்போது உங்கள் <xliff:g id="DEVICE">%1$s</xliff:g> சாதனத்தில் இதை அணுக முடியாது. அதற்குப் பதிலாக உங்கள் Android TV சாதனத்தில் பயன்படுத்திப் பார்க்கவும்."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"தற்போது உங்கள் <xliff:g id="DEVICE">%1$s</xliff:g> சாதனத்தில் இதை அணுக முடியாது. அதற்குப் பதிலாக உங்கள் டேப்லெட்டில் பயன்படுத்திப் பார்க்கவும்."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"தற்போது உங்கள் <xliff:g id="DEVICE">%1$s</xliff:g> சாதனத்தில் இதை அணுக முடியாது. அதற்குப் பதிலாக உங்கள் மொபைலில் பயன்படுத்திப் பார்க்கவும்."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"இந்த ஆப்ஸ் கூடுதல் பாதுகாப்பைக் கோருகிறது. அதற்குப் பதிலாக உங்கள் Android TV சாதனத்தில் பயன்படுத்திப் பார்க்கவும்."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"இந்த ஆப்ஸ் கூடுதல் பாதுகாப்பைக் கோருகிறது. அதற்குப் பதிலாக உங்கள் டேப்லெட்டில் பயன்படுத்திப் பார்க்கவும்."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"இந்த ஆப்ஸ் கூடுதல் பாதுகாப்பைக் கோருகிறது. அதற்குப் பதிலாக உங்கள் மொபைலில் பயன்படுத்திப் பார்க்கவும்."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"இந்த ஆப்ஸ் Android இன் பழைய பதிப்புக்காக உருவாக்கப்பட்டதால், சரியாக வேலை செய்யாமல் போகலாம். புதுப்பிப்புகள் ஏதேனும் உள்ளதா எனப் பார்க்கவும் அல்லது டெவெலப்பரைத் தொடர்புகொள்ளவும்."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"புதுப்பிப்பு உள்ளதா எனப் பார்"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"புதிய செய்திகள் வந்துள்ளன"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"மேலும் அறிந்து மாற்ற, தட்டவும்."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"தொந்தரவு செய்ய வேண்டாம் அமைப்புகள் மாற்றப்பட்டன"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"எவற்றையெல்லாம் தடுக்கிறது என்பதைப் பார்க்க, தட்டவும்."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"அறிவிப்பு அமைப்புகளை மதிப்பாய்வு செய்யுங்கள்"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13ல், நீங்கள் நிறுவுகின்ற ஆப்ஸ் உங்களுக்கு அறிவிப்புகளை அனுப்ப உங்கள் அனுமதி தேவை. ஏற்கெனவே உள்ள ஆப்ஸுக்கு இந்த அனுமதியை மாற்ற தட்டவும்."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"பின்னர் நினைவூட்டு"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"நிராகரி"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"சிஸ்டம்"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"அமைப்புகள்"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"கேமரா"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> மொழிபெயர்க்கப்பட்டது."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"<xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> மொழியிலிருந்து <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> மொழிக்கு மெசேஜ் மொழிபெயர்க்கப்பட்டது."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"பின்னணிச் செயல்பாடு"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"ஆப்ஸ் பேட்டரியைப் பயன்படுத்துகிறது"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"ஆப்ஸ் செயல்பாட்டில் உள்ளது"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> ஆப்ஸ் பேட்டரியைப் பின்னணியில் பயன்படுத்துகிறது. பார்க்க தட்டவும்."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> பேட்டரியின் ஆயுளைப் பாதிக்கலாம். செயலிலுள்ள ஆப்ஸைப் பார்க்க தட்டவும்."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"செயலிலுள்ள ஆப்ஸைப் பாருங்கள்"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"உங்கள் <xliff:g id="DEVICE">%1$s</xliff:g> சாதனத்திலிருந்து மொபைலின் கேமராவை அணுக முடியாது"</string> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index 851d17e6bcb4..1c3d4fce719f 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -1132,7 +1132,7 @@ <string name="paste" msgid="461843306215520225">"అతికించు"</string> <string name="paste_as_plain_text" msgid="7664800665823182587">"సాదా వచనం లాగా అతికించు"</string> <string name="replace" msgid="7842675434546657444">"భర్తీ చేయండి..."</string> - <string name="delete" msgid="1514113991712129054">"తొలగించు"</string> + <string name="delete" msgid="1514113991712129054">"తొలగించండి"</string> <string name="copyUrl" msgid="6229645005987260230">"URLని కాపీ చేయి"</string> <string name="selectTextMode" msgid="3225108910999318778">"వచనాన్ని ఎంచుకోండి"</string> <string name="undo" msgid="3175318090002654673">"చర్య రద్దు చేయి"</string> @@ -1140,7 +1140,7 @@ <string name="autofill" msgid="511224882647795296">"ఆటోఫిల్"</string> <string name="textSelectionCABTitle" msgid="5151441579532476940">"వచన ఎంపిక"</string> <string name="addToDictionary" msgid="8041821113480950096">"నిఘంటువుకు జోడించు"</string> - <string name="deleteText" msgid="4200807474529938112">"తొలగించు"</string> + <string name="deleteText" msgid="4200807474529938112">"తొలగించండి"</string> <string name="inputMethod" msgid="1784759500516314751">"ఇన్పుట్ పద్ధతి"</string> <string name="editTextMenuTitle" msgid="857666911134482176">"వచనానికి సంబంధించిన చర్యలు"</string> <string name="input_method_nav_back_button_desc" msgid="3655838793765691787">"వెనుకకు"</string> @@ -1151,9 +1151,9 @@ <string name="app_running_notification_title" msgid="8985999749231486569">"<xliff:g id="APP_NAME">%1$s</xliff:g> అమలులో ఉంది"</string> <string name="app_running_notification_text" msgid="5120815883400228566">"మరింత సమాచారం కోసం లేదా యాప్ను ఆపివేయడం కోసం నొక్కండి."</string> <string name="ok" msgid="2646370155170753815">"సరే"</string> - <string name="cancel" msgid="6908697720451760115">"రద్దు చేయి"</string> + <string name="cancel" msgid="6908697720451760115">"రద్దు చేయండి"</string> <string name="yes" msgid="9069828999585032361">"సరే"</string> - <string name="no" msgid="5122037903299899715">"రద్దు చేయి"</string> + <string name="no" msgid="5122037903299899715">"రద్దు చేయండి"</string> <string name="dialog_alert_title" msgid="651856561974090712">"గమనిక"</string> <string name="loading" msgid="3138021523725055037">"లోడ్ చేస్తోంది…"</string> <string name="capital_on" msgid="2770685323900821829">"ఆన్లో ఉంది"</string> @@ -1318,7 +1318,7 @@ <string name="sms_short_code_details" msgid="2723725738333388351">"దీని వలన మీ మొబైల్ ఖాతాకు "<b>"ఛార్జీలు విధించబడవచ్చు"</b>"."</string> <string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>"దీని వలన మీ మొబైల్ ఖాతాకు ఛార్జీలు విధించబడవచ్చు."</b></string> <string name="sms_short_code_confirm_allow" msgid="920477594325526691">"పంపు"</string> - <string name="sms_short_code_confirm_deny" msgid="1356917469323768230">"రద్దు చేయి"</string> + <string name="sms_short_code_confirm_deny" msgid="1356917469323768230">"రద్దు చేయండి"</string> <string name="sms_short_code_remember_choice" msgid="1374526438647744862">"నా ఎంపికను గుర్తుంచుకో"</string> <string name="sms_short_code_remember_undo_instruction" msgid="2620984439143080410">"మీరు దీన్ని తర్వాత సెట్టింగ్లు > అనువర్తనాలులో మార్చవచ్చు"</string> <string name="sms_short_code_confirm_always_allow" msgid="2223014893129755950">"ఎల్లప్పుడూ అనుమతించు"</string> @@ -1492,7 +1492,7 @@ <string name="vpn_lockdown_config" msgid="8331697329868252169">"నెట్వర్క్ లేదా VPN సెట్టింగ్లను మార్చండి"</string> <string name="upload_file" msgid="8651942222301634271">"ఫైల్ను ఎంచుకోండి"</string> <string name="no_file_chosen" msgid="4146295695162318057">"ఫైల్ ఎంచుకోబడలేదు"</string> - <string name="reset" msgid="3865826612628171429">"రీసెట్ చేయి"</string> + <string name="reset" msgid="3865826612628171429">"రీసెట్ చేయండి"</string> <string name="submit" msgid="862795280643405865">"సమర్పించు"</string> <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"డ్రైవింగ్ యాప్ అమలవుతోంది"</string> <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"డ్రైవింగ్ యాప్ నుండి నిష్క్రమించడం కోసం నొక్కండి."</string> @@ -1541,8 +1541,8 @@ <string name="date_picker_prev_month_button" msgid="3418694374017868369">"మునుపటి నెల"</string> <string name="date_picker_next_month_button" msgid="4858207337779144840">"తర్వాత నెల"</string> <string name="keyboardview_keycode_alt" msgid="8997420058584292385">"Alt"</string> - <string name="keyboardview_keycode_cancel" msgid="2134624484115716975">"రద్దు చేయి"</string> - <string name="keyboardview_keycode_delete" msgid="2661117313730098650">"తొలగించు"</string> + <string name="keyboardview_keycode_cancel" msgid="2134624484115716975">"రద్దు చేయండి"</string> + <string name="keyboardview_keycode_delete" msgid="2661117313730098650">"తొలగించండి"</string> <string name="keyboardview_keycode_done" msgid="2524518019001653851">"పూర్తయింది"</string> <string name="keyboardview_keycode_mode_change" msgid="2743735349997999020">"మోడ్ మార్పు"</string> <string name="keyboardview_keycode_shift" msgid="3026509237043975573">"షిఫ్ట్"</string> @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ప్రస్తుతం అందుబాటులో లేదు."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> అందుబాటులో లేదు"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"అనుమతి అవసరం"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"కెమెరా అందుబాటులో లేదు"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"ఫోన్లో కొనసాగించండి"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"మైక్రోఫోన్ అందుబాటులో లేదు"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV సెట్టింగ్లు అందుబాటులో లేవు"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"టాబ్లెట్ సెట్టింగ్లు అందుబాటులో లేవు"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"ఫోన్ సెట్టింగ్లు అందుబాటులో లేవు"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"మీ <xliff:g id="DEVICE">%1$s</xliff:g>లో దీన్ని యాక్సెస్ చేయడం సాధ్యపడదు. బదులుగా మీ Android TV పరికరంలో ట్రై చేయండి."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"మీ <xliff:g id="DEVICE">%1$s</xliff:g>లో దీన్ని యాక్సెస్ చేయడం సాధ్యపడదు. బదులుగా మీ టాబ్లెట్లో ట్రై చేయండి."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"మీ <xliff:g id="DEVICE">%1$s</xliff:g>లో దీన్ని యాక్సెస్ చేయడం సాధ్యపడదు. బదులుగా మీ ఫోన్లో ట్రై చేయండి."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"ఈ సమయంలో మీ <xliff:g id="DEVICE">%1$s</xliff:g>లో దీన్ని యాక్సెస్ చేయడం సాధ్యపడదు. బదులుగా మీ Android TV పరికరంలో ట్రై చేయండి."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"ఈ సమయంలో మీ <xliff:g id="DEVICE">%1$s</xliff:g>లో దీన్ని యాక్సెస్ చేయడం సాధ్యపడదు. బదులుగా మీ టాబ్లెట్లో ట్రై చేయండి."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"ఈ సమయంలో మీ <xliff:g id="DEVICE">%1$s</xliff:g>లో దీన్ని యాక్సెస్ చేయడం సాధ్యపడదు. బదులుగా మీ ఫోన్లో ట్రై చేయండి."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"ఈ యాప్ అదనపు సెక్యూరిటీ కోసం రిక్వెస్ట్ చేస్తోంది. బదులుగా మీ Android TV పరికరంలో ట్రై చేయండి."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"ఈ యాప్ అదనపు సెక్యూరిటీ కోసం రిక్వెస్ట్ చేస్తోంది. బదులుగా మీ టాబ్లెట్లో ట్రై చేయండి."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"ఈ యాప్ అదనపు సెక్యూరిటీ కోసం రిక్వెస్ట్ చేస్తోంది. బదులుగా మీ ఫోన్లో ట్రై చేయండి."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"ఈ యాప్ పాత వెర్షన్ Android కోసం రూపొందించబడింది మరియు అది సరిగ్గా పని చేయకపోవచ్చు. అప్డేట్ల కోసం తనిఖీ చేయడానికి ప్రయత్నించండి లేదా డెవలపర్ని సంప్రదించండి."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"అప్డేట్ కోసం తనిఖీ చేయండి"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"మీకు కొత్త మెసేజ్లు ఉన్నాయి"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"మరింత తెలుసుకోవడానికి మరియు మార్చడానికి నొక్కండి."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"అంతరాయం కలిగించవద్దు మార్చబడింది"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"బ్లాక్ చేయబడిన దాన్ని తనిఖీ చేయడానికి నొక్కండి."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"నోటిఫికేషన్ సెట్టింగ్లను రివ్యూ చేయండి"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13లో, మీరు ఇన్స్టాల్ చేసే యాప్లకు నోటిఫికేషన్లను పంపడానికి మీ అనుమతి అవసరం. ఇప్పటికే ఉన్న యాప్ల కోసం ఈ అనుమతిని మార్చడానికి ట్యాప్ చేయండి."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"తర్వాత గుర్తు చేయి"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"విస్మరించండి"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"సిస్టమ్"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"సెట్టింగ్లు"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"కెమెరా"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> అనువదించబడింది."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"మెసేజ్ <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> నుండి <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>కు అనువదించబడింది."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"బ్యాక్గ్రౌండ్ యాక్టివిటీ"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"యాప్ బ్యాటరీని ఉపయోగిస్తోంది"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"యాప్ ఇప్పటికీ యాక్టివ్గా ఉంది"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"బ్యాక్గ్రౌండ్లో <xliff:g id="APP">%1$s</xliff:g> బ్యాటరీని ఉపయోగిస్తోంది. రివ్యూ చేయడానికి ట్యాప్ చేయండి."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> బ్యాటరీ జీవితకాలాన్ని ప్రభావితం చేయవచ్చు. యాక్టివ్ యాప్లను రివ్యూ చేయడానికి ట్యాప్ చేయండి."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"యాక్టివ్గా ఉన్న యాప్లను చెక్ చేయండి"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"మీ <xliff:g id="DEVICE">%1$s</xliff:g> నుండి ఫోన్ కెమెరాను యాక్సెస్ చేయడం సాధ్యపడదు"</string> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index adf04ed7ba1e..d52428329119 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -1681,9 +1681,9 @@ <string name="accessibility_enable_service_title" msgid="3931558336268541484">"อนุญาตให้ <xliff:g id="SERVICE">%1$s</xliff:g> ควบคุมอุปกรณ์อย่างเต็มที่ไหม"</string> <string name="accessibility_service_warning_description" msgid="291674995220940133">"การควบคุมอย่างเต็มที่เหมาะสำหรับแอปที่ช่วยคุณในเรื่องความต้องการความช่วยเหลือพิเศษแต่ไม่เหมาะสำหรับแอปส่วนใหญ่"</string> <string name="accessibility_service_screen_control_title" msgid="190017412626919776">"ดูและควบคุมหน้าจอ"</string> - <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"การควบคุมนี้อ่านเนื้อหาทั้งหมดบนหน้าจอและแสดงเนื้อหาทับแอปอื่นๆ"</string> + <string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"การควบคุมนี้สามารถอ่านเนื้อหาทั้งหมดบนหน้าจอและแสดงเนื้อหาทับแอปอื่นๆ"</string> <string name="accessibility_service_action_perform_title" msgid="779670378951658160">"ดูและดำเนินการ"</string> - <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"การกระทำนี้ติดตามการโต้ตอบของคุณกับแอปหรือกับเซ็นเซอร์ของฮาร์ดแวร์ และจะโต้ตอบกับแอปต่างๆ แทนคุณ"</string> + <string name="accessibility_service_action_perform_description" msgid="2718852014003170558">"การควบคุมนี้สามารถติดตามการโต้ตอบของคุณกับแอปหรือกับเซ็นเซอร์ของฮาร์ดแวร์ และโต้ตอบกับแอปต่างๆ แทนคุณ"</string> <string name="accessibility_dialog_button_allow" msgid="2092558122987144530">"อนุญาต"</string> <string name="accessibility_dialog_button_deny" msgid="4129575637812472671">"ปฏิเสธ"</string> <string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"แตะฟีเจอร์เพื่อเริ่มใช้"</string> @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ไม่พร้อมใช้งานในขณะนี้"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ไม่พร้อมใช้งาน"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"ต้องการสิทธิ์"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"กล้องไม่พร้อมใช้งาน"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"ดำเนินการต่อบนโทรศัพท์"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"ไมโครโฟนไม่พร้อมใช้งาน"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"การตั้งค่า Android TV ไม่พร้อมใช้งาน"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"การตั้งค่าแท็บเล็ตไม่พร้อมใช้งาน"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"การตั้งค่าโทรศัพท์ไม่พร้อมใช้งาน"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"เข้าถึงแอปนี้ใน <xliff:g id="DEVICE">%1$s</xliff:g> ของคุณไม่ได้ โปรดลองเข้าถึงในอุปกรณ์ Android TV แทน"</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"เข้าถึงแอปนี้ใน <xliff:g id="DEVICE">%1$s</xliff:g> ของคุณไม่ได้ โปรดลองเข้าถึงในแท็บเล็ตแทน"</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"เข้าถึงแอปนี้ใน <xliff:g id="DEVICE">%1$s</xliff:g> ของคุณไม่ได้ โปรดลองเข้าถึงในโทรศัพท์แทน"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"เข้าถึงแอปนี้ใน <xliff:g id="DEVICE">%1$s</xliff:g> ของคุณไม่ได้ในขณะนี้ โปรดลองเข้าถึงในอุปกรณ์ Android TV แทน"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"เข้าถึงแอปนี้ใน <xliff:g id="DEVICE">%1$s</xliff:g> ของคุณไม่ได้ในขณะนี้ โปรดลองเข้าถึงในแท็บเล็ตแทน"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"เข้าถึงแอปนี้ใน <xliff:g id="DEVICE">%1$s</xliff:g> ของคุณไม่ได้ในขณะนี้ โปรดลองเข้าถึงในโทรศัพท์แทน"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"แอปนี้มีการขอการรักษาความปลอดภัยเพิ่มเติม โปรดลองเข้าถึงในอุปกรณ์ Android TV แทน"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"แอปนี้มีการขอการรักษาความปลอดภัยเพิ่มเติม โปรดลองเข้าถึงในแท็บเล็ตแทน"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"แอปนี้มีการขอการรักษาความปลอดภัยเพิ่มเติม โปรดลองเข้าถึงในโทรศัพท์แทน"</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"แอปนี้สร้างขึ้นเพื่อ Android เวอร์ชันเก่าและอาจทำงานผิดปกติ โปรดลองตรวจหาการอัปเดตหรือติดต่อนักพัฒนาซอฟต์แวร์"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"ตรวจสอบอัปเดต"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"คุณมีข้อความใหม่"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"แตะเพื่อดูข้อมูลเพิ่มเติมและเปลี่ยนแปลง"</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"เปลี่ยน \"ห้ามรบกวน\" แล้ว"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"แตะเพื่อดูรายการที่ถูกบล็อก"</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"ตรวจสอบการตั้งค่าการแจ้งเตือน"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"ใน Android 13 แอปที่คุณติดตั้งจะต้องได้รับสิทธิ์จากคุณเพื่อส่งการแจ้งเตือน แตะเพื่อเปลี่ยนแปลงสิทธิ์นี้สำหรับแอปที่มีอยู่"</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"เตือนภายหลัง"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"ปิด"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"ระบบ"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"การตั้งค่า"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"กล้อง"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> แปลแล้ว"</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"แปลข้อความจากภาษา<xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>เป็นภาษา<xliff:g id="TO_LANGUAGE">%2$s</xliff:g>แล้ว"</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"กิจกรรมในเบื้องหลัง"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"แอปกำลังใช้แบตเตอรี่"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"แอปทำให้แบตเตอรี่หมดเร็ว"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"แอปยังทำงานอยู่"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> กำลังใช้แบตเตอรี่ในเบื้องหลัง แตะเพื่อตรวจสอบ"</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> ทำงานอยู่เบื้องหลัง แตะเพื่อจัดการการใช้งานแบตเตอรี่"</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> อาจส่งผลต่ออายุการใช้งานแบตเตอรี่ แตะเพื่อตรวจสอบแอปที่ทำงานอยู่"</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"ตรวจสอบแอปที่ใช้งานอยู่"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"เข้าถึงกล้องของโทรศัพท์จาก <xliff:g id="DEVICE">%1$s</xliff:g> ไม่ได้"</string> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index a195c8857c4e..d0504747e3b2 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"Hindi available sa ngayon ang <xliff:g id="APP_NAME">%1$s</xliff:g>."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"Hindi available ang <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Kailangan ng pahintulot"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Hindi available ang camera"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Magpatuloy sa telepono"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Hindi available ang mikropono"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Hindi available ang mga setting ng Android TV"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Hindi available ang mga setting ng tablet"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Hindi available ang mga setting ng telepono"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Hindi ito maa-access sa iyong <xliff:g id="DEVICE">%1$s</xliff:g>. Subukan na lang sa iyong Android TV device."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Hindi ito maa-access sa iyong <xliff:g id="DEVICE">%1$s</xliff:g>. Subukan na lang sa iyong tablet."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Hindi ito maa-access sa iyong <xliff:g id="DEVICE">%1$s</xliff:g>. Subukan na lang sa iyong telepono."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Hindi ito maa-access sa iyong <xliff:g id="DEVICE">%1$s</xliff:g> sa ngayon. Subukan na lang sa iyong Android TV device."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Hindi ito maa-access sa iyong <xliff:g id="DEVICE">%1$s</xliff:g> sa ngayon. Subukan na lang sa iyong tablet."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Hindi ito maa-access sa iyong <xliff:g id="DEVICE">%1$s</xliff:g> sa ngayon. Subukan na lang sa iyong telepono."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Humihiling ng karagdagang seguridad ang app na ito. Subukan na lang sa iyong Android TV device."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Humihiling ng karagdagang seguridad ang app na ito. Subukan na lang sa iyong tablet."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Humihiling ng karagdagang seguridad ang app na ito. Subukan na lang sa iyong telepono."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ang app na ito ay ginawa para sa mas lumang bersyon ng Android at maaaring hindi gumana nang maayos. Subukang tingnan kung may mga update, o makipag-ugnayan sa developer."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Tingnan kung may update"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Mayroon kang mga bagong mensahe"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"I-tap para matuto pa at baguhin."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Binago ang Huwag Istorbohin"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"I-tap para tingnan kung ano ang naka-block."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Suriin ang mga setting ng notification"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Sa Android 13, kakailanganin ng mga app na na-install mo ng pahintulot para magpadala ng mga notification. I-tap para baguhin ang pahintulot na ito para sa mga kasalukuyang app."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Ipaalala mamaya"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"I-dismiss"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"System"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Mga Setting"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Camera"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Naisalin ang <xliff:g id="MESSAGE">%1$s</xliff:g>."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Naisalin ang mensahe sa <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> mula sa <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Aktibidad sa Background"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"May app na gumagamit ng baterya"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"May app na nagde-drain ng baterya"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"May app na aktibo pa rin"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"Gumagamit ng baterya ang <xliff:g id="APP">%1$s</xliff:g> sa background. I-tap para suriin."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"Tumatakbo ang <xliff:g id="APP">%1$s</xliff:g> sa background. I-tap para pamahalaan ang paggamit ng baterya."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"Posibleng maapektuhan ng <xliff:g id="APP">%1$s</xliff:g> ang tagal ng baterya. I-tap para suriin ang mga aktibong app."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Tingnan ang mga aktibong app"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Hindi ma-access ang camera ng telepono mula sa iyong <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index 1313b96b2bef..fbfec602e42a 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulaması şu anda kullanılamıyor."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> kullanılamıyor"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"İzin gerekli"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kamera kullanılamıyor"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"İşleme telefonda devam edin"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofon kullanılamıyor"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV ayarları kullanılamıyor"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Tablet ayarları kullanılamıyor"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Telefon ayarları kullanılamıyor"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Bu uygulamaya <xliff:g id="DEVICE">%1$s</xliff:g> cihazınızdan erişilemiyor. Bunun yerine Android TV cihazınızı kullanmayı deneyin."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Bu uygulamaya <xliff:g id="DEVICE">%1$s</xliff:g> cihazınızdan erişilemiyor. Bunun yerine tabletinizi kullanmayı deneyin."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Bu uygulamaya <xliff:g id="DEVICE">%1$s</xliff:g> cihazınızdan erişilemiyor. Bunun yerine telefonunuzu kullanmayı deneyin."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Bu uygulamaya şu anda <xliff:g id="DEVICE">%1$s</xliff:g> cihazınızdan erişilemiyor. Bunun yerine Android TV cihazınızı kullanmayı deneyin."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Bu uygulamaya şu anda <xliff:g id="DEVICE">%1$s</xliff:g> cihazınızdan erişilemiyor. Bunun yerine tabletinizi kullanmayı deneyin."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Bu uygulamaya şu anda <xliff:g id="DEVICE">%1$s</xliff:g> cihazınızdan erişilemiyor. Bunun yerine telefonunuzu kullanmayı deneyin."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Bu uygulama daha fazla güvenlik istiyor. Bunun yerine Android TV cihazınızı kullanmayı deneyin."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Bu uygulama daha fazla güvenlik istiyor. Bunun yerine tabletinizi kullanmayı deneyin."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Bu uygulama daha fazla güvenlik istiyor. Bunun yerine telefonunuzu kullanmayı deneyin."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Bu uygulama Android\'in daha eski bir sürümü için oluşturuldu ve düzgün çalışmayabilir. Güncellemeleri kontrol etmeyi deneyin veya geliştiriciyle iletişime geçin."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Güncellemeleri denetle"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Yeni mesajlarınız var"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Daha fazla bilgi edinmek ve değiştirmek için dokunun."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Rahatsız Etmeyin modu değişti"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Nelerin engellendiğini kontrol etmek için dokunun."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Bildirim ayarlarını inceleyin"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13\'te yüklediğiniz uygulamaların bildirim göndermek için izninize ihtiyacı vardır. Mevcut uygulamalarda bu izni değiştirmek için dokunun."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Sonra hatırlat"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Kapat"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Sistem"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Ayarlar"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Kamera"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> Çevrildi."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Mesajın, <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>-<xliff:g id="TO_LANGUAGE">%2$s</xliff:g> çevirisi yapıldı."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Arka Plan Etkinliği"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Pil kullanan bir uygulama var"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Hâlâ etkin olan bir uygulama var"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> uygulaması arka planda pil kullanıyor. İncelemek için dokunun."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> uygulaması pil ömrünü etkileyebilir. Etkin uygulamaları incelemek için dokunun."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Etkin uygulamaları kontrol edin"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"<xliff:g id="DEVICE">%1$s</xliff:g> cihazınızdan telefonun kamerasına erişilemiyor"</string> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index 29d5c5e0c790..ec4e52cbbac4 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -2069,14 +2069,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Торкніться, щоб дізнатися більше та змінити."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Налаштування режиму \"Не турбувати\" змінено"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Торкніться, щоб перевірити, що заблоковано."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Перегляньте налаштування сповіщень"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"В ОС Android 13 встановленим додаткам потрібно надати дозвіл, щоб вони могли надсилати сповіщення. Натисніть, щоб змінити цей дозвіл для наявних додатків."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Нагадати пізніше"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Закрити"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Система"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Налаштування"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Камера"</string> @@ -2295,9 +2291,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> (перекладене повідомлення)."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Повідомлення перекладено (мова оригіналу: <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>, мова перекладу: <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>)."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Робота у фоновому режимі"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Додаток споживає заряд акумулятора"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Додаток досі активний"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"Додаток <xliff:g id="APP">%1$s</xliff:g> споживає заряд акумулятора у фоновому режимі. Натисніть, щоб переглянути."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"Додаток <xliff:g id="APP">%1$s</xliff:g> може вплинути на час роботи акумулятора. Натисніть, щоб переглянути активні додатки."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Перевірте активні додатки"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Не вдається отримати доступ до камери телефона з пристрою <xliff:g id="DEVICE">%1$s</xliff:g>"</string> diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml index fb69ba300b6e..80f88497934f 100644 --- a/core/res/res/values-ur/strings.xml +++ b/core/res/res/values-ur/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ابھی دستیاب نہیں ہے۔"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> دستیاب نہیں ہے"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"اجازت درکار ہے"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"کیمرا دستیاب نہیں ہے"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"فون پر جاری رکھیں"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"مائیکروفون دستیاب نہیں ہے"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV کی ترتیبات دستیاب نہیں ہے"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"ٹیبلیٹ کی ترتیبات دستیاب نہیں ہے"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"فون کی ترتیبات دستیاب نہیں ہے"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"آپ کے <xliff:g id="DEVICE">%1$s</xliff:g> پر اس تک رسائی حاصل نہیں ہو سکتی۔ اس کے بجائے اپنے Android TV آلے پر کوشش کریں۔"</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"آپ کے <xliff:g id="DEVICE">%1$s</xliff:g> پر اس تک رسائی حاصل نہیں ہو سکتی۔ اس کے بجائے اپنے ٹیبلیٹ پر کوشش کریں۔"</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"آپ کے <xliff:g id="DEVICE">%1$s</xliff:g> پر اس تک رسائی حاصل نہیں ہو سکتی۔ اس کے بجائے اپنے فون پر کوشش کریں۔"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"اس وقت آپ کے <xliff:g id="DEVICE">%1$s</xliff:g> پر اس تک رسائی حاصل نہیں ہو سکتی۔ اس کے بجائے اپنے Android TV آلے پر کوشش کریں۔"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"اس وقت آپ کے <xliff:g id="DEVICE">%1$s</xliff:g> پر اس تک رسائی حاصل نہیں ہو سکتی۔ اس کے بجائے اپنے ٹیبلیٹ پر کوشش کریں۔"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"اس وقت آپ کے <xliff:g id="DEVICE">%1$s</xliff:g> پر اس تک رسائی حاصل نہیں ہو سکتی۔ اس کے بجائے اپنے فون پر کوشش کریں۔"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"یہ ایپ اضافی سیکیورٹی کی درخواست کر رہی ہے۔ اس کے بجائے اپنے Android TV آلے پر کوشش کریں۔"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"یہ ایپ اضافی سیکیورٹی کی درخواست کر رہی ہے۔ اس کے بجائے اپنے ٹیبلیٹ پر کوشش کریں۔"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"یہ ایپ اضافی سیکیورٹی کی درخواست کر رہی ہے۔ اس کے بجائے اپنے فون پر کوشش کریں۔"</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"یہ ایپ Android کے پرانے ورژن کے لئے بنائی گئی ہے اور ہو سکتا ہے صحیح طور پر کام نہ کرے۔ اپ ڈیٹس چیک کر کے آزمائیں یا ڈویلپر سے رابطہ کریں۔"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"اپ ڈیٹ چیک کریں"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"آپ کے پاس نئے پیغامات ہیں"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"مزید جاننے اور تبدیل کرنے کیلئے تھپتھپائیں۔"</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"\'ڈسٹرب نہ کریں\' تبدیل ہو گيا ہے"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"مسدود کی گئی چیزوں کو چیک کرنے کے لیے تھپتھپائیں۔"</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"اطلاع کی ترتیبات کا جائزہ لیں"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13 میں، اطلاعات بھیجنے کے لیے آپ کے انسٹال کردہ ایپس کو آپ کی اجازت درکار ہوتی ہے۔ موجودہ ایپس کے لیے اس اجازت کو تبدیل کرنے کی خاطر تھپتھپائیں۔"</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"بعد میں یاد دلائیں"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"برخاست کریں"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"سسٹم"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"ترتیبات"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"کیمرا"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> کا ترجمہ کیا گیا۔"</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"پیغام کا ترجمہ <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> سے<xliff:g id="TO_LANGUAGE">%2$s</xliff:g> میں کیا گیا۔"</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"پس منظر کی سرگرمی"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"ایک ایپ بیٹری کا استعمال کر رہی ہے"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"ایک ایپ اب بھی فعال ہے"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> ایپ پس منظر میں بیٹری استعمال کر رہی ہے۔ جائزے کے لیے تھپتھپائیں۔"</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> ایپ بیٹری لائف کو متاثر کر سکتی ہے۔ فعال ایپس کا جائزہ لینے کے لیے تھپتھپائیں۔"</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"فعال ایپس چیک کریں"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"آپ کے <xliff:g id="DEVICE">%1$s</xliff:g> سے فون کے کیمرا تک رسائی حاصل نہیں کی جا سکتی"</string> diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml index afea5853aa1a..e00860e9dee7 100644 --- a/core/res/res/values-uz/strings.xml +++ b/core/res/res/values-uz/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"Ayni vaqtda <xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi ishlamayapti."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> kanali ish faoliyatida emas"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Ruxsat zarur"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Kamera ishlamayapti"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Telefonda davom ettirish"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Mikrofon ishlamayapti"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV sozlamalari ishlamayapti"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Planshet sozlamalari ishlamayapti"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Telefon sozlamalari ishlamayapti"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Bu <xliff:g id="DEVICE">%1$s</xliff:g> qurilmangizda ochilmaydi. Android TV qurilmasi orqali urinib koʻring."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Bu <xliff:g id="DEVICE">%1$s</xliff:g> qurilmangizda ochilmaydi. Planshet orqali urinib koʻring."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Bu <xliff:g id="DEVICE">%1$s</xliff:g> qurilmangizda ochilmaydi. Telefon orqali urininb koʻring."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Ayni vaqtda bu translatsiya <xliff:g id="DEVICE">%1$s</xliff:g> qurilmangizda ishlamaydi. Android TV qurilmasi orqali urinib koʻring."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Ayni vaqtda bu translatsiya <xliff:g id="DEVICE">%1$s</xliff:g> qurilmangizda ishlamaydi. Planshet orqali urinib koʻring."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Ayni vaqtda bu translatsiya <xliff:g id="DEVICE">%1$s</xliff:g> qurilmangizda ishlamaydi. Telefon orqali urininb koʻring."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Bu ilova qoʻshimcha himoyani talab qilmoqda. Android TV qurilmasi orqali urinib koʻring."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Bu ilova qoʻshimcha himoyani talab qilmoqda. Planshet orqali urinib koʻring."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Bu ilova qoʻshimcha himoyani talab qilmoqda. Telefon orqali urininb koʻring."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Bu ilova eskiroq Android versiyalariga chiqarilgan va xato ishlashi mumkin. Yangilanishlarini tekshiring yoki dasturchi bilan bog‘laning."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Yangilanish borligini tekshirish"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Sizga yangi SMS keldi"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Batafsil axborot olish va o‘zgartirish uchun bosing."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Bezovta qilinmasin rejimi sozlamalari o‘zgartirildi"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Nimalar bloklanganini tekshirish uchun bosing"</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Bildirishnoma sozlamalarini tekshiring"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Android 13 versiyasida oʻrnatiladigan ilovalar bildirishnoma yuborishiga ruxsat talab etiladi. Mavjud ilovalar uchun bu ruxsatni oʻzgartirish uchun bosing."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Keyinroq eslatilsin"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Yopish"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Tizim"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Sozlamalar"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Kamera"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> tarjima qilindi."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Xabar <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> tilidan <xliff:g id="TO_LANGUAGE">%2$s</xliff:g> tiliga tarjima qilindi."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Fondagi harakatlar"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Ilova batareyadan foydalanmoqda"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"Ilova batareyani koʻp sarflamoqda"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Ilova hali ham faol"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> orqa fonda batareyadan foydalanmoqda. Tekshirish uchun bosing."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"<xliff:g id="APP">%1$s</xliff:g> ilovasi fonda ishlamoqda. Batareya sarfini boshqarish uchun bosing."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> batareya quvvatiga taʼsir qiladi. Faol ilovalarni koʻrib chiqish uchun bosing."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Faol ilovalarni tekshiring"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"<xliff:g id="DEVICE">%1$s</xliff:g> qurilmasidan telefonning kamerasiga kirish imkonsiz"</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index db2855c7ff6c..944b02d60fb4 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> hiện không dùng được."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"Không hỗ trợ <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Cần có quyền"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Không dùng được máy ảnh"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Tiếp tục trên điện thoại"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Không dùng được micrô"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Không dùng được các chế độ cài đặt của Android TV"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Không dùng được các chế độ cài đặt của máy tính bảng"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Không dùng được các chế độ cài đặt của điện thoại"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Hiện tại, bạn không thể truy cập vào ứng dụng này trên <xliff:g id="DEVICE">%1$s</xliff:g>. Hãy thử trên thiết bị Android TV."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Hiện tại, bạn không thể truy cập vào ứng dụng này trên <xliff:g id="DEVICE">%1$s</xliff:g>. Hãy thử trên máy tính bảng."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Hiện tại, bạn không thể truy cập vào ứng dụng này trên <xliff:g id="DEVICE">%1$s</xliff:g>. Hãy thử trên điện thoại."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Hiện tại, bạn không thể truy cập vào ứng dụng này trên <xliff:g id="DEVICE">%1$s</xliff:g>. Hãy thử trên thiết bị Android TV."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Hiện tại, bạn không thể truy cập vào ứng dụng này trên <xliff:g id="DEVICE">%1$s</xliff:g>. Hãy thử trên máy tính bảng."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Hiện tại, bạn không thể truy cập vào ứng dụng này trên <xliff:g id="DEVICE">%1$s</xliff:g>. Hãy thử trên điện thoại."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Ứng dụng này đang yêu cầu tính năng bảo mật bổ sung. Hãy thử trên thiết bị Android TV."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Ứng dụng này đang yêu cầu tính năng bảo mật bổ sung. Hãy thử trên máy tính bảng."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Ứng dụng này đang yêu cầu tính năng bảo mật bổ sung. Hãy thử trên điện thoại."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Ứng dụng này được xây dựng cho một phiên bản Android cũ hơn và có thể hoạt động không bình thường. Hãy thử kiểm tra các bản cập nhật hoặc liên hệ với nhà phát triển."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Kiểm tra bản cập nhật"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Bạn có tin nhắn mới"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Nhấn để tìm hiểu thêm và thay đổi."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Cài đặt Không làm phiền đã thay đổi"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Nhấn để xem những thông báo bị chặn."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Xem lại chế độ cài đặt thông báo"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Trên Android 13, các ứng dụng mà bạn cài đặt sẽ cần bạn cấp quyền gửi thông báo. Hãy nhấn để thay đổi quyền này cho các ứng dụng hiện có."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Nhắc tôi sau"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Đóng"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Hệ thống"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Cài đặt"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Máy ảnh"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"Đã dịch <xliff:g id="MESSAGE">%1$s</xliff:g>."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Đã dịch thông báo từ <xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> sang <xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Hoạt động trong nền"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"Một ứng dụng đang sử dụng pin"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"Một ứng dụng vẫn đang hoạt động"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"<xliff:g id="APP">%1$s</xliff:g> đang sử dụng pin trong nền. Hãy nhấn để xem."</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"<xliff:g id="APP">%1$s</xliff:g> có thể ảnh hưởng đến thời lượng pin. Hãy nhấn để xem các ứng dụng đang hoạt động."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Xem các ứng dụng đang hoạt động"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Không truy cập được vào máy ảnh trên điện thoại từ <xliff:g id="DEVICE">%1$s</xliff:g> của bạn"</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index c049efc94ef8..2053b6a4d992 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g>目前无法使用。"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g>不可用"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"需要权限"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"无法使用摄像头"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"继续在手机上操作"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"无法使用麦克风"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"无法使用 Android TV 设置"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"无法使用平板电脑设置"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"无法使用手机设置"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"无法在您的<xliff:g id="DEVICE">%1$s</xliff:g>上访问此应用,您可以尝试在 Android TV 设备上访问。"</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"无法在您的<xliff:g id="DEVICE">%1$s</xliff:g>上访问此应用,您可以尝试在平板电脑上访问。"</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"无法在您的<xliff:g id="DEVICE">%1$s</xliff:g>上访问此应用,您可以尝试在手机上访问。"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"目前无法在您的<xliff:g id="DEVICE">%1$s</xliff:g>上访问此应用,您可以尝试在 Android TV 设备上访问。"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"目前无法在您的<xliff:g id="DEVICE">%1$s</xliff:g>上访问此应用,您可以尝试在平板电脑上访问。"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"目前无法在您的<xliff:g id="DEVICE">%1$s</xliff:g>上访问此应用,您可以尝试在手机上访问。"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"此应用要求进行额外的安全性验证,您可以尝试在 Android TV 设备上访问。"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"此应用要求进行额外的安全性验证,您可以尝试在平板电脑上访问。"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"此应用要求进行额外的安全性验证,您可以尝试在手机上访问。"</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"此应用专为旧版 Android 打造,因此可能无法正常运行。请尝试检查更新或与开发者联系。"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"检查更新"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"您有新消息"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"点按即可了解详情以及进行更改。"</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"“勿扰”设置有变更"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"点按即可查看屏蔽内容。"</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"查看通知设置"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"在 Android 13 中,您安装的应用需要您授予相应权限才能发送通知。点按即可为现有应用更改此权限。"</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"稍后提醒我"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"关闭"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"系统"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"设置"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"相机"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"已翻译“<xliff:g id="MESSAGE">%1$s</xliff:g>”。"</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"已将消息内容从<xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>翻译成<xliff:g id="TO_LANGUAGE">%2$s</xliff:g>。"</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"后台活动"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"某个应用正在消耗电量"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"某个应用正在消耗大量电池电量"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"某个应用仍在使用中"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"“<xliff:g id="APP">%1$s</xliff:g>”正在后台消耗电量。点按即可查看。"</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"“<xliff:g id="APP">%1$s</xliff:g>”正在后台运行。点按即可管理电池用量。"</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"“<xliff:g id="APP">%1$s</xliff:g>”可能会影响电池续航时间。点按即可查看使用中的应用。"</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"查看使用中的应用"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"无法从<xliff:g id="DEVICE">%1$s</xliff:g>上访问手机的摄像头"</string> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index 732faa025144..eb07e300c129 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"目前無法使用「<xliff:g id="APP_NAME">%1$s</xliff:g>」。"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"無法使用「<xliff:g id="ACTIVITY">%1$s</xliff:g>」"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"需要權限"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"無法使用相機"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"請繼續在手機上操作"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"無法使用麥克風"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"無法使用 Android TV 設定"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"無法使用平板電腦設定"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"無法使用手機設定"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"無法在 <xliff:g id="DEVICE">%1$s</xliff:g> 上存取這個應用程式,請改用 Android TV 裝置。"</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"無法在 <xliff:g id="DEVICE">%1$s</xliff:g> 上存取這個應用程式,請改用平板電腦。"</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"無法在 <xliff:g id="DEVICE">%1$s</xliff:g> 上存取這個應用程式,請改用手機。"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"目前無法在 <xliff:g id="DEVICE">%1$s</xliff:g> 上存取這個應用程式,請改用 Android TV 裝置。"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"目前無法在 <xliff:g id="DEVICE">%1$s</xliff:g> 上存取這個應用程式,請改用平板電腦。"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"目前無法在 <xliff:g id="DEVICE">%1$s</xliff:g> 上存取這個應用程式,請改用手機。"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"這個應用程式要求進行額外的安全性驗證,請改用 Android TV 裝置。"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"這個應用程式要求進行額外的安全性驗證,請改用平板電腦。"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"這個應用程式要求進行額外的安全性驗證,請改用手機。"</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"此應用程式專為舊版 Android 打造,因此可能無法正常運作。請嘗試檢查更新,或與開發人員聯絡。"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"檢查更新"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"您有新的訊息"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"輕按即可瞭解詳情和作出變更。"</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"請勿騷擾已變更"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"輕按即可查看封鎖內容。"</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"查看通知設定"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"在 Android 13 中,您安裝的應用程式須獲得授權才能傳送通知。輕按即可變更現有應用程式的這項權限。"</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"稍後提醒我"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"關閉"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"系統"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"設定"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"相機"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"翻譯咗「<xliff:g id="MESSAGE">%1$s</xliff:g>」。"</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"已經將訊息由<xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>翻譯成<xliff:g id="TO_LANGUAGE">%2$s</xliff:g>。"</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"背景活動"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"某個應用程式正在使用電量"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"一個應用程式正在消耗電池"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"某個應用程式目前仍在運作"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"「<xliff:g id="APP">%1$s</xliff:g>」正在背景使用電量。輕按即可查看。"</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"「<xliff:g id="APP">%1$s</xliff:g>」正在背景執行。輕按即可管理電池用量。"</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"「<xliff:g id="APP">%1$s</xliff:g>」可能會影響電池壽命。輕按即可查看使用中的應用程式。"</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"查看使用中的應用程式"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"無法從 <xliff:g id="DEVICE">%1$s</xliff:g> 存取手機的相機"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 403bf1a0d9ca..44dba0be8eb9 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」目前無法使用。"</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"無法存取「<xliff:g id="ACTIVITY">%1$s</xliff:g>」"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"需要相關權限"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"無法使用相機"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"請繼續在手機上操作"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"無法使用麥克風"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"無法使用 Android TV 設定"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"無法使用平板電腦設定"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"無法使用手機設定"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"無法在 <xliff:g id="DEVICE">%1$s</xliff:g> 上存取這個應用程式,請改用 Android TV 裝置。"</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"無法在 <xliff:g id="DEVICE">%1$s</xliff:g> 上存取這個應用程式,請改用平板電腦。"</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"無法在 <xliff:g id="DEVICE">%1$s</xliff:g> 上存取這個應用程式,請改用手機。"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"目前無法在 <xliff:g id="DEVICE">%1$s</xliff:g> 上存取這個應用程式,請改用 Android TV 裝置。"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"目前無法在 <xliff:g id="DEVICE">%1$s</xliff:g> 上存取這個應用程式,請改用平板電腦。"</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"目前無法在 <xliff:g id="DEVICE">%1$s</xliff:g> 上存取這個應用程式,請改用手機。"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"這個應用程式要求進行額外的安全性驗證,請改用 Android TV 裝置。"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"這個應用程式要求進行額外的安全性驗證,請改用平板電腦。"</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"這個應用程式要求進行額外的安全性驗證,請改用手機。"</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"這個應用程式是專為舊版 Android 所打造,因此可能無法正常運作。請嘗試檢查更新,或是與開發人員聯絡。"</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"檢查更新"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"你有新訊息"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"輕觸即可瞭解詳情及進行變更。"</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"「零打擾」設定已變更"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"輕觸即可查看遭封鎖的項目。"</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"查看通知設定"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"在 Android 13 中,你安裝的應用程式必須獲得授權,才能傳送通知。輕觸即可變更現有應用程式的這項權限。"</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"稍後提醒我"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"關閉"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"系統"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"設定"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"相機"</string> @@ -2293,9 +2274,11 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"已翻譯<xliff:g id="MESSAGE">%1$s</xliff:g>。"</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"訊息內容已從<xliff:g id="FROM_LANGUAGE">%1$s</xliff:g>翻成<xliff:g id="TO_LANGUAGE">%2$s</xliff:g>。"</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"背景活動"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"某個應用程式正在消耗電池電力"</string> + <!-- no translation found for notification_title_abusive_bg_apps (994230770856147656) --> + <skip /> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"某個應用程式目前仍在運作"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"「<xliff:g id="APP">%1$s</xliff:g>」應用程式正在背景消耗電池電力。輕觸即可查看。"</string> + <!-- no translation found for notification_content_abusive_bg_apps (5296898075922695259) --> + <skip /> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"「<xliff:g id="APP">%1$s</xliff:g>」應用程式可能會影響電池續航力。輕觸即可查看使用中的應用程式。"</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"查看使用中的應用程式"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"無法從 <xliff:g id="DEVICE">%1$s</xliff:g> 存取手機的相機"</string> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index cf9e05f91305..76c39ac35ccb 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -1933,36 +1933,21 @@ <string name="app_blocked_message" msgid="542972921087873023">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> ayitholakali khona manje."</string> <string name="app_streaming_blocked_title" msgid="6090945835898766139">"okungatholakali <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string> <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Kudingeka imvume"</string> - <!-- no translation found for app_streaming_blocked_title_for_camera_dialog (3935701653713853065) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_fingerprint_dialog (3516853717714141951) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_microphone_dialog (544822455127171206) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (196994247017450357) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (8222710146267948647) --> - <skip /> - <!-- no translation found for app_streaming_blocked_title_for_settings_dialog (6895719984375299791) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (5024599278277957935) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (7491114163056552686) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message (1245180131667647277) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6306583663205997979) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (6545624942642129664) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_permission_dialog (8462740631707923000) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (3470977315395784567) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (698460091901465092) --> - <skip /> - <!-- no translation found for app_streaming_blocked_message_for_fingerprint_dialog (8552691971910603907) --> - <skip /> + <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Ikhamera ayitholakali"</string> + <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Qhubeka kufoni"</string> + <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Imakrofoni ayitholakali"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Amasethingi e-Android TV awatholakali"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"Amasethingi ethebulethi awatholakali"</string> + <string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"Amasethingi efoni awatholakali"</string> + <string name="app_streaming_blocked_message" product="tv" msgid="5024599278277957935">"Lokhu akukwazi ukufinyelelwa ku-<xliff:g id="DEVICE">%1$s</xliff:g> yakho. Zama kudivayisi yakho ye-Android TV kunalokho."</string> + <string name="app_streaming_blocked_message" product="tablet" msgid="7491114163056552686">"Lokhu akukwazi ukufinyelelwa ku-<xliff:g id="DEVICE">%1$s</xliff:g> yakho. Zama kuthebhulethi yakho kunalokho."</string> + <string name="app_streaming_blocked_message" product="default" msgid="1245180131667647277">"Lokhu akukwazi ukufinyelelwa ku-<xliff:g id="DEVICE">%1$s</xliff:g> yakho. Zama efonini yakho kunalokho."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tv" msgid="6306583663205997979">"Lokhu akukwazi ukufinyelelwa ku-<xliff:g id="DEVICE">%1$s</xliff:g> yakho ngalesi sikhathi. Zama kudivayisi yakho ye-Android TV kunalokho."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="tablet" msgid="6545624942642129664">"Lokhu akukwazi ukufinyelelwa ku-<xliff:g id="DEVICE">%1$s</xliff:g> yakho ngalesi sikhathi. Zama kuthebhulethi yakho kunalokho."</string> + <string name="app_streaming_blocked_message_for_permission_dialog" product="default" msgid="8462740631707923000">"Lokhu akukwazi ukufinyelelwa ku-<xliff:g id="DEVICE">%1$s</xliff:g> yakho ngalesi sikhathi. Zama efonini yakho kunalokho."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Le app icela ukuvikeleka okwengeziwe. Zama kudivayisi yakho ye-Android TV kunalokho."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Le app icela ukuvikeleka okwengeziwe. Zama kuthebhulethi yakho kunalokho."</string> + <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Le app icela ukuvikeleka okwengeziwe. Zama efonini yakho kunalokho."</string> <string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Lolu hlelo lokusebenza belakhelwe inguqulo endala ye-Android futhi kungenzeka lungasebenzi kahle. Zama ukuhlolela izibuyekezo, noma uxhumane nonjiniyela."</string> <string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Hlola izibuyekezo"</string> <string name="new_sms_notification_title" msgid="6528758221319927107">"Unemilayezo emisha"</string> @@ -2067,14 +2052,10 @@ <string name="zen_upgrade_notification_visd_content" msgid="3683314609114134946">"Thepha ukuze ufunde kabanzi futhi ushintshe."</string> <string name="zen_upgrade_notification_title" msgid="8198167698095298717">"Ukungaphazamisi kushintshile"</string> <string name="zen_upgrade_notification_content" msgid="5228458567180124005">"Thepha ukuze uhlole ukuthi yini evinjelwe."</string> - <!-- no translation found for review_notification_settings_title (5102557424459810820) --> - <skip /> - <!-- no translation found for review_notification_settings_text (5696497037817525074) --> - <skip /> - <!-- no translation found for review_notification_settings_remind_me_action (1081081018678480907) --> - <skip /> - <!-- no translation found for review_notification_settings_dismiss (4160916504616428294) --> - <skip /> + <string name="review_notification_settings_title" msgid="5102557424459810820">"Buyekeza amasethingi wesaziso"</string> + <string name="review_notification_settings_text" msgid="5696497037817525074">"Ku-Android 13, ama-app owafakayo adinga imvume yakho yokuthumela izaziso. Thepha ukuze ushintshe le mvume yama-app akhona kakade."</string> + <string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Ngikhumbuze ngesinye isikhathi"</string> + <string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Chitha"</string> <string name="notification_app_name_system" msgid="3045196791746735601">"Isistimu"</string> <string name="notification_app_name_settings" msgid="9088548800899952531">"Izilungiselelo"</string> <string name="notification_appops_camera_active" msgid="8177643089272352083">"Ikhamera"</string> @@ -2293,9 +2274,9 @@ <string name="ui_translation_accessibility_translated_text" msgid="3197547218178944544">"<xliff:g id="MESSAGE">%1$s</xliff:g> Uhunyushiwe."</string> <string name="ui_translation_accessibility_translation_finished" msgid="3057830947610088465">"Umlayezo uhunyushwe kusuka ku-<xliff:g id="FROM_LANGUAGE">%1$s</xliff:g> kuya ku-<xliff:g id="TO_LANGUAGE">%2$s</xliff:g>."</string> <string name="notification_channel_abusive_bg_apps" msgid="6092140213264920355">"Umsebenzi Wangemuva"</string> - <string name="notification_title_abusive_bg_apps" msgid="3258460527676573815">"I-app isebenzisa ibhethri"</string> + <string name="notification_title_abusive_bg_apps" msgid="994230770856147656">"I-app idla ibhethri"</string> <string name="notification_title_long_running_fgs" msgid="8170284286477131587">"I-app isasebenza"</string> - <string name="notification_content_abusive_bg_apps" msgid="9180610713603474720">"I-<xliff:g id="APP">%1$s</xliff:g> isebenzisa ibhethri kungemuva. Thepha ukuze ubuyekeze."</string> + <string name="notification_content_abusive_bg_apps" msgid="5296898075922695259">"I-<xliff:g id="APP">%1$s</xliff:g> isebenza kungemuva. Thepha ukuze ulawule ukusetshenziswa kwebhethri."</string> <string name="notification_content_long_running_fgs" msgid="8258193410039977101">"I-<xliff:g id="APP">%1$s</xliff:g> ingase ithinte impilo yebhethri. Thepha ukuze ubuyekeze ama-app asebenzayo."</string> <string name="notification_action_check_bg_apps" msgid="4758877443365362532">"Hlola ama-app asebenzayo"</string> <string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"Ayikwazi ukufinyelela ikhamera yefoni kusuka ku-<xliff:g id="DEVICE">%1$s</xliff:g> yakho"</string> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 35bed2d76425..757f40963bf7 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -674,6 +674,10 @@ <!-- Indicates whether to enable hinge angle sensor when using unfold animation --> <bool name="config_unfoldTransitionHingeAngle">false</bool> + <!-- Indicates the time needed to time out the fold animation if the device stops in half folded + mode. --> + <integer name="config_unfoldTransitionHalfFoldedTimeout">600</integer> + <!-- Indicates that the device supports having more than one internal display on at the same time. Only applicable to devices with more than one internal display. If this option is set to false, DisplayManager will make additional effort to ensure no more than 1 internal @@ -3804,6 +3808,9 @@ <!-- True if the device supports running activities on secondary displays. --> <bool name="config_supportsMultiDisplay">true</bool> + <!-- Indicates whether the device supports bubble notifications or not. --> + <bool name="config_supportsBubble">true</bool> + <!-- True if the device has no home screen. That is a launcher activity where the user can launch other applications from. --> <bool name="config_noHomeScreen">false</bool> @@ -5737,6 +5744,12 @@ --> <bool name="config_bg_prompt_fgs_with_noti_to_bg_restricted">false</bool> + <!-- The behavior when the system detects it's abusive, should the system prompt the user + to put it into the bg restricted level. + True - we'll show the prompt to user, False - we'll not show it. + --> + <bool name="config_bg_prompt_abusive_apps_to_bg_restricted">false</bool> + <!-- The types of state where we'll exempt its battery usage during that state. The state here must be one or a combination of STATE_TYPE_* in BaseAppStateTracker. --> diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml index cd3578c727f0..77500c42c6bf 100644 --- a/core/res/res/values/config_telephony.xml +++ b/core/res/res/values/config_telephony.xml @@ -17,9 +17,9 @@ <resources> <!-- This file defines Android telephony related resources --> - <!-- Whether force to enable telephony new data stack or not --> - <bool name="config_force_enable_telephony_new_data_stack">true</bool> - <java-symbol type="bool" name="config_force_enable_telephony_new_data_stack" /> + <!-- Whether force disabling telephony new data stack or not --> + <bool name="config_force_disable_telephony_new_data_stack">false</bool> + <java-symbol type="bool" name="config_force_disable_telephony_new_data_stack" /> <!-- Configure tcp buffer sizes per network type in the form: network-type:rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 323c72667c33..d9d1a082ed4a 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -39,14 +39,17 @@ <!-- Elevation of toast view --> <dimen name="toast_elevation">2dp</dimen> + <!-- The default height of the status bar used in {@link SystemBarUtils#getStatusBarHeight} to + calculate the status bar height. --> + <dimen name="status_bar_height_default">24dp</dimen> <!-- Height of the status bar. Do not read this dimen directly. Use {@link SystemBarUtils#getStatusBarHeight} instead. --> - <dimen name="status_bar_height">24dp</dimen> + <dimen name="status_bar_height">@dimen/status_bar_height_portrait</dimen> <!-- Height of the status bar in portrait. Do not read this dimen directly. Use {@link SystemBarUtils#getStatusBarHeight} instead. --> - <dimen name="status_bar_height_portrait">@dimen/status_bar_height</dimen> + <dimen name="status_bar_height_portrait">24dp</dimen> <!-- Height of the status bar in landscape. Do not read this dimen directly. Use {@link SystemBarUtils#getStatusBarHeight} instead. --> @@ -779,6 +782,10 @@ <dimen name="notification_left_icon_start">@dimen/notification_icon_circle_start</dimen> <!-- The alpha of a disabled notification button --> <item type="dimen" format="float" name="notification_action_disabled_alpha">0.5</item> + <!-- The maximum size of Person avatar image in MessagingStyle notifications. + This is bigger than displayed because listeners can use it for other displays + e.g. wearables. --> + <dimen name="notification_person_icon_max_size">144dp</dimen> <!-- The maximum size of the small notification icon on low memory devices. --> <dimen name="notification_small_icon_size_low_ram">@dimen/notification_small_icon_size</dimen> @@ -792,6 +799,10 @@ <dimen name="notification_big_picture_max_width_low_ram">294dp</dimen> <!-- The size of the right icon image when on low ram --> <dimen name="notification_right_icon_size_low_ram">@dimen/notification_right_icon_size</dimen> + <!-- The maximum size of Person avatar image in MessagingStyle notifications. + This is bigger than displayed because listeners can use it for other displays + e.g. wearables. --> + <dimen name="notification_person_icon_max_size_low_ram">96dp</dimen> <!-- The maximum size of the grayscale icon --> <dimen name="notification_grayscale_icon_max_size">256dp</dimen> diff --git a/core/res/res/values/public-final.xml b/core/res/res/values/public-final.xml index 19a484293b0a..85325fec7277 100644 --- a/core/res/res/values/public-final.xml +++ b/core/res/res/values/public-final.xml @@ -3222,4 +3222,184 @@ <public type="id" name="accessibilityActionDragDrop" id="0x01020056" /> <public type="id" name="accessibilityActionDragCancel" id="0x01020057" /> + <!-- =============================================================== + Resources added in version T of the platform + + NOTE: After this version of the platform is forked, changes cannot be made to the root + branch's groups for that release. Only merge changes to the forked platform branch. + =============================================================== --> + <eat-comment/> + + <staging-public-group-final type="attr" first-id="0x01df0000"> + <public name="sharedUserMaxSdkVersion" /> + <public name="requiredSplitTypes" /> + <public name="splitTypes" /> + <public name="canDisplayOnRemoteDevices" /> + <public name="supportedTypes" /> + <public name="resetEnabledSettingsOnAppDataCleared" /> + <public name="supportsStylusHandwriting" /> + <public name="showClockAndComplications" /> + <!-- @hide @SystemApi --> + <public name="gameSessionService" /> + <public name="supportsBatteryGameMode" /> + <public name="supportsPerformanceGameMode" /> + <public name="allowGameAngleDriver" /> + <public name="allowGameDownscaling" /> + <public name="allowGameFpsOverride" /> + <public name="localeConfig" /> + <public name="showBackdrop" /> + <public name="removed_useTargetActivityForQuickAccess"/> + <public name="removed_inheritKeyStoreKeys" /> + <public name="preferKeepClear" /> + <public name="autoHandwritingEnabled" /> + <public name="fromExtendLeft" /> + <public name="fromExtendTop" /> + <public name="fromExtendRight" /> + <public name="fromExtendBottom" /> + <public name="toExtendLeft" /> + <public name="toExtendTop" /> + <public name="toExtendRight" /> + <public name="toExtendBottom" /> + <public name="tileService" /> + <public name="windowSplashScreenBehavior" /> + <public name="allowUntrustedActivityEmbedding" /> + <public name="knownActivityEmbeddingCerts" /> + <public name="intro" /> + <public name="enableOnBackInvokedCallback" /> + <public name="supportsInlineSuggestionsWithTouchExploration" /> + <public name="lineBreakStyle" /> + <public name="lineBreakWordStyle" /> + <!-- @hide --> + <public name="maxDrawableWidth" /> + <!-- @hide --> + <public name="maxDrawableHeight" /> + <public name="backdropColor" /> + </staging-public-group-final> + + <public type="attr" name="sharedUserMaxSdkVersion" id="0x0101064d" /> + <public type="attr" name="requiredSplitTypes" id="0x0101064e" /> + <public type="attr" name="splitTypes" id="0x0101064f" /> + <public type="attr" name="canDisplayOnRemoteDevices" id="0x01010650" /> + <public type="attr" name="supportedTypes" id="0x01010651" /> + <public type="attr" name="resetEnabledSettingsOnAppDataCleared" id="0x01010652" /> + <public type="attr" name="supportsStylusHandwriting" id="0x01010653" /> + <public type="attr" name="showClockAndComplications" id="0x01010654" /> + <!-- @hide @SystemApi --> + <public type="attr" name="gameSessionService" id="0x01010655" /> + <public type="attr" name="supportsBatteryGameMode" id="0x01010656" /> + <public type="attr" name="supportsPerformanceGameMode" id="0x01010657" /> + <public type="attr" name="allowGameAngleDriver" id="0x01010658" /> + <public type="attr" name="allowGameDownscaling" id="0x01010659" /> + <public type="attr" name="allowGameFpsOverride" id="0x0101065a" /> + <public type="attr" name="localeConfig" id="0x0101065b" /> + <public type="attr" name="showBackdrop" id="0x0101065c" /> + <public type="attr" name="preferKeepClear" id="0x0101065d" /> + <public type="attr" name="autoHandwritingEnabled" id="0x0101065e" /> + <public type="attr" name="fromExtendLeft" id="0x0101065f" /> + <public type="attr" name="fromExtendTop" id="0x01010660" /> + <public type="attr" name="fromExtendRight" id="0x01010661" /> + <public type="attr" name="fromExtendBottom" id="0x01010662" /> + <public type="attr" name="toExtendLeft" id="0x01010663" /> + <public type="attr" name="toExtendTop" id="0x01010664" /> + <public type="attr" name="toExtendRight" id="0x01010665" /> + <public type="attr" name="toExtendBottom" id="0x01010666" /> + <public type="attr" name="tileService" id="0x01010667" /> + <public type="attr" name="windowSplashScreenBehavior" id="0x01010668" /> + <public type="attr" name="allowUntrustedActivityEmbedding" id="0x01010669" /> + <public type="attr" name="knownActivityEmbeddingCerts" id="0x0101066a" /> + <public type="attr" name="intro" id="0x0101066b" /> + <public type="attr" name="enableOnBackInvokedCallback" id="0x0101066c" /> + <public type="attr" name="supportsInlineSuggestionsWithTouchExploration" id="0x0101066d" /> + <public type="attr" name="lineBreakStyle" id="0x0101066e" /> + <public type="attr" name="lineBreakWordStyle" id="0x0101066f" /> + <!-- @hide --> + <public type="attr" name="maxDrawableWidth" id="0x01010670" /> + <!-- @hide --> + <public type="attr" name="maxDrawableHeight" id="0x01010671" /> + <public type="attr" name="backdropColor" id="0x01010672" /> + + <staging-public-group-final type="id" first-id="0x01de0000"> + <public name="removed_accessibilityActionSwipeLeft" /> + <public name="removed_accessibilityActionSwipeRight" /> + <public name="removed_accessibilityActionSwipeUp" /> + <public name="removed_accessibilityActionSwipeDown" /> + <public name="accessibilityActionShowTextSuggestions" /> + <public name="inputExtractAction" /> + <public name="inputExtractAccessories" /> + </staging-public-group-final> + + <public type="id" name="accessibilityActionShowTextSuggestions" id="0x01020058" /> + <public type="id" name="inputExtractAction" id="0x01020059" /> + <public type="id" name="inputExtractAccessories" id="0x0102005a" /> + + <staging-public-group-final type="style" first-id="0x01dd0000"> + <public name="TextAppearance.DeviceDefault.Headline" /> + </staging-public-group-final> + + <public type="style" name="TextAppearance.DeviceDefault.Headline" id="0x010302e5" /> + + <staging-public-group-final type="string" first-id="0x01dc0000"> + <!-- @hide @SystemApi --> + <public name="config_systemSupervision" /> + <!-- @hide @SystemApi --> + <public name="config_devicePolicyManagement" /> + <!-- @hide @SystemApi --> + <public name="config_systemAppProtectionService" /> + <!-- @hide @SystemApi @TestApi --> + <public name="config_systemAutomotiveCalendarSyncManager" /> + <!-- @hide @SystemApi --> + <public name="config_defaultAutomotiveNavigation" /> + <!-- @hide @SystemApi --> + <public name="safety_protection_display_text" /> + <!-- @hide @SystemApi --> + <public name="config_systemSettingsIntelligence" /> + <!-- @hide --> + <public name="config_systemBluetoothStack" /> + </staging-public-group-final> + + <!-- @hide @SystemApi --> + <public type="string" name="config_systemSupervision" id="0x0104003c" /> + <!-- @hide @SystemApi --> + <public type="string" name="config_devicePolicyManagement" id="0x0104003d" /> + <!-- @hide @SystemApi --> + <public type="string" name="config_systemAppProtectionService" id="0x0104003e" /> + <!-- @hide @SystemApi @TestApi --> + <public type="string" name="config_systemAutomotiveCalendarSyncManager" id="0x0104003f" /> + <!-- @hide @SystemApi --> + <public type="string" name="config_defaultAutomotiveNavigation" id="0x01040040" /> + <!-- @hide @SystemApi --> + <public type="string" name="safety_protection_display_text" id="0x01040041" /> + <!-- @hide @SystemApi --> + <public type="string" name="config_systemSettingsIntelligence" id="0x01040042" /> + <!-- @hide --> + <public type="string" name="config_systemBluetoothStack" id="0x01040043" /> + + <staging-public-group-final type="array" first-id="0x01d90000"> + <!-- @hide @SystemApi --> + <public name="config_optionalIpSecAlgorithms" /> + </staging-public-group-final> + + <!-- @hide @SystemApi --> + <public type="array" name="config_optionalIpSecAlgorithms" id="0x01070006" /> + + <staging-public-group-final type="drawable" first-id="0x01d80000"> + <!-- @hide @SystemApi --> + <public name="ic_safety_protection" /> + </staging-public-group-final> + + <!-- @hide @SystemApi --> + <public type="drawable" name="ic_safety_protection" id="0x010800b5" /> + + <staging-public-group-final type="bool" first-id="0x01cf0000"> + <!-- @hide @TestApi --> + <public name="config_preventImeStartupUnlessTextEditor" /> + <!-- @hide @SystemApi --> + <public name="config_enableQrCodeScannerOnLockScreen" /> + </staging-public-group-final> + + <!-- @hide @TestApi --> + <public type="bool" name="config_preventImeStartupUnlessTextEditor" id="0x01110007" /> + <!-- @hide @SystemApi --> + <public type="bool" name="config_enableQrCodeScannerOnLockScreen" id="0x01110008" /> + </resources> diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml index 86bad7f12258..f09ffbe4466b 100644 --- a/core/res/res/values/public-staging.xml +++ b/core/res/res/values/public-staging.xml @@ -102,140 +102,65 @@ <resources> <!-- =============================================================== - Resources added in version T of the platform + Resources added in version U of the platform NOTE: After this version of the platform is forked, changes cannot be made to the root branch's groups for that release. Only merge changes to the forked platform branch. =============================================================== --> <eat-comment/> - <staging-public-group type="attr" first-id="0x01df0000"> - <public name="sharedUserMaxSdkVersion" /> - <public name="requiredSplitTypes" /> - <public name="splitTypes" /> - <public name="canDisplayOnRemoteDevices" /> - <public name="supportedTypes" /> - <public name="resetEnabledSettingsOnAppDataCleared" /> - <public name="supportsStylusHandwriting" /> - <public name="showClockAndComplications" /> - <!-- @hide @SystemApi --> - <public name="gameSessionService" /> - <public name="supportsBatteryGameMode" /> - <public name="supportsPerformanceGameMode" /> - <public name="allowGameAngleDriver" /> - <public name="allowGameDownscaling" /> - <public name="allowGameFpsOverride" /> - <public name="localeConfig" /> - <public name="showBackdrop" /> - <public name="removed_useTargetActivityForQuickAccess"/> - <public name="removed_inheritKeyStoreKeys" /> - <public name="preferKeepClear" /> - <public name="autoHandwritingEnabled" /> - <public name="fromExtendLeft" /> - <public name="fromExtendTop" /> - <public name="fromExtendRight" /> - <public name="fromExtendBottom" /> - <public name="toExtendLeft" /> - <public name="toExtendTop" /> - <public name="toExtendRight" /> - <public name="toExtendBottom" /> - <public name="tileService" /> - <public name="windowSplashScreenBehavior" /> - <public name="allowUntrustedActivityEmbedding" /> - <public name="knownActivityEmbeddingCerts" /> - <public name="intro" /> - <public name="enableOnBackInvokedCallback" /> - <public name="supportsInlineSuggestionsWithTouchExploration" /> - <public name="lineBreakStyle" /> - <public name="lineBreakWordStyle" /> - <!-- @hide --> - <public name="maxDrawableWidth" /> - <!-- @hide --> - <public name="maxDrawableHeight" /> - <public name="backdropColor" /> + <staging-public-group type="attr" first-id="0x01ce0000"> </staging-public-group> - <staging-public-group type="id" first-id="0x01de0000"> - <public name="removed_accessibilityActionSwipeLeft" /> - <public name="removed_accessibilityActionSwipeRight" /> - <public name="removed_accessibilityActionSwipeUp" /> - <public name="removed_accessibilityActionSwipeDown" /> - <public name="accessibilityActionShowTextSuggestions" /> - <public name="inputExtractAction" /> - <public name="inputExtractAccessories" /> + <staging-public-group type="id" first-id="0x01cd0000"> </staging-public-group> - <staging-public-group type="style" first-id="0x01dd0000"> - <public name="TextAppearance.DeviceDefault.Headline" /> + <staging-public-group type="style" first-id="0x01cc0000"> </staging-public-group> - <staging-public-group type="string" first-id="0x01dc0000"> - <!-- @hide @SystemApi --> - <public name="config_systemSupervision" /> - <!-- @hide @SystemApi --> - <public name="config_devicePolicyManagement" /> - <!-- @hide @SystemApi --> - <public name="config_systemAppProtectionService" /> - <!-- @hide @SystemApi @TestApi --> - <public name="config_systemAutomotiveCalendarSyncManager" /> - <!-- @hide @SystemApi --> - <public name="config_defaultAutomotiveNavigation" /> - <!-- @hide @SystemApi --> - <public name="safety_protection_display_text" /> - <!-- @hide @SystemApi --> - <public name="config_systemSettingsIntelligence" /> - <!-- @hide --> - <public name="config_systemBluetoothStack" /> + <staging-public-group type="string" first-id="0x01cb0000"> </staging-public-group> - <staging-public-group type="dimen" first-id="0x01db0000"> + <staging-public-group type="dimen" first-id="0x01ca0000"> </staging-public-group> - <staging-public-group type="color" first-id="0x01da0000"> + <staging-public-group type="color" first-id="0x01c90000"> </staging-public-group> - <staging-public-group type="array" first-id="0x01d90000"> - <!-- @hide @SystemApi --> - <public name="config_optionalIpSecAlgorithms" /> + <staging-public-group type="array" first-id="0x01c80000"> </staging-public-group> - <staging-public-group type="drawable" first-id="0x01d80000"> - <!-- @hide @SystemApi --> - <public name="ic_safety_protection" /> + <staging-public-group type="drawable" first-id="0x01c70000"> </staging-public-group> - <staging-public-group type="layout" first-id="0x01d70000"> + <staging-public-group type="layout" first-id="0x01c60000"> </staging-public-group> - <staging-public-group type="anim" first-id="0x01d60000"> + <staging-public-group type="anim" first-id="0x01c50000"> </staging-public-group> - <staging-public-group type="animator" first-id="0x01d50000"> + <staging-public-group type="animator" first-id="0x01c40000"> </staging-public-group> - <staging-public-group type="interpolator" first-id="0x01d40000"> + <staging-public-group type="interpolator" first-id="0x01c30000"> </staging-public-group> - <staging-public-group type="mipmap" first-id="0x01d30000"> + <staging-public-group type="mipmap" first-id="0x01c20000"> </staging-public-group> - <staging-public-group type="integer" first-id="0x01d20000"> + <staging-public-group type="integer" first-id="0x01c10000"> </staging-public-group> - <staging-public-group type="transition" first-id="0x01d10000"> + <staging-public-group type="transition" first-id="0x01c00000"> </staging-public-group> - <staging-public-group type="raw" first-id="0x01d00000"> + <staging-public-group type="raw" first-id="0x01bf0000"> </staging-public-group> - <staging-public-group type="bool" first-id="0x01cf0000"> - <!-- @hide @TestApi --> - <public name="config_preventImeStartupUnlessTextEditor" /> - <!-- @hide @SystemApi --> - <public name="config_enableQrCodeScannerOnLockScreen" /> + <staging-public-group type="bool" first-id="0x01be0000"> </staging-public-group> - <staging-public-group type="fraction" first-id="0x01ce0000"> + <staging-public-group type="fraction" first-id="0x01bd0000"> </staging-public-group> </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 004cb4c8b630..6104701f2158 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -6292,12 +6292,12 @@ ul.</string> <!-- Title for the notification channel notifying user of abusive background apps. [CHAR LIMIT=NONE] --> <string name="notification_channel_abusive_bg_apps">Background Activity</string> <!-- Title of notification indicating abusive background apps. [CHAR LIMIT=NONE] --> - <string name="notification_title_abusive_bg_apps">An app is using battery</string> + <string name="notification_title_abusive_bg_apps">An app is draining battery</string> <!-- Title of notification indicating long running foreground services. [CHAR LIMIT=NONE] --> <string name="notification_title_long_running_fgs">An app is still active</string> <!-- Content of notification indicating abusive background apps. [CHAR LIMIT=NONE] --> <string name="notification_content_abusive_bg_apps"> - <xliff:g id="app" example="Gmail">%1$s</xliff:g> is using battery in the background. Tap to review. + <xliff:g id="app" example="Gmail">%1$s</xliff:g> is running in the background. Tap to manage battery usage. </string> <!-- Content of notification indicating long running foreground service. [CHAR LIMIT=NONE] --> <string name="notification_content_long_running_fgs"> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 7a9f520b4d3c..c07404bf141d 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -1503,15 +1503,13 @@ please see styles_device_defaults.xml. <style name="AllowLogAccess"> <item name="android:layout_width">332dp</item> <item name="android:textSize">24sp</item> - <item name="android:textColor">@android:color/system_neutral1_900</item> <item name="android:fontFamily">google-sans</item> </style> <style name="PrimaryAllowLogAccess"> <item name="android:layout_width">332dp</item> <item name="android:textSize">14sp</item> - <item name="android:textColor">@android:color/system_neutral1_900</item> - <item name="android:fontFamily">google-sans</item> + <item name="android:fontFamily">google-sans-text</item> </style> <style name="PermissionGrantButtonTop" diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index f177226c4ec3..333482272789 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -379,6 +379,7 @@ <java-symbol type="bool" name="config_supportSpeakerNearUltrasound" /> <java-symbol type="bool" name="config_supportAudioSourceUnprocessed" /> <java-symbol type="bool" name="config_freeformWindowManagement" /> + <java-symbol type="bool" name="config_supportsBubble" /> <java-symbol type="bool" name="config_supportsMultiWindow" /> <java-symbol type="bool" name="config_supportsSplitScreenMultiWindow" /> <java-symbol type="bool" name="config_supportsMultiDisplay" /> @@ -3603,6 +3604,7 @@ <java-symbol type="dimen" name="notification_actions_icon_drawable_size"/> <java-symbol type="dimen" name="notification_custom_view_max_image_height"/> <java-symbol type="dimen" name="notification_custom_view_max_image_width"/> + <java-symbol type="dimen" name="notification_person_icon_max_size" /> <java-symbol type="dimen" name="notification_small_icon_size_low_ram"/> <java-symbol type="dimen" name="notification_big_picture_max_height_low_ram"/> @@ -3611,6 +3613,7 @@ <java-symbol type="dimen" name="notification_grayscale_icon_max_size"/> <java-symbol type="dimen" name="notification_custom_view_max_image_height_low_ram"/> <java-symbol type="dimen" name="notification_custom_view_max_image_width_low_ram"/> + <java-symbol type="dimen" name="notification_person_icon_max_size_low_ram" /> <!-- Accessibility fingerprint gestures --> <java-symbol type="string" name="capability_title_canCaptureFingerprintGestures" /> @@ -3954,6 +3957,7 @@ <java-symbol type="bool" name="config_supportsConcurrentInternalDisplays" /> <java-symbol type="bool" name="config_unfoldTransitionEnabled" /> <java-symbol type="bool" name="config_unfoldTransitionHingeAngle" /> + <java-symbol type="integer" name="config_unfoldTransitionHalfFoldedTimeout" /> <java-symbol type="array" name="config_perDeviceStateRotationLockDefaults" /> @@ -4761,6 +4765,7 @@ <java-symbol type="integer" name="config_bg_current_drain_media_playback_min_duration" /> <java-symbol type="integer" name="config_bg_current_drain_location_min_duration" /> <java-symbol type="bool" name="config_bg_prompt_fgs_with_noti_to_bg_restricted" /> + <java-symbol type="bool" name="config_bg_prompt_abusive_apps_to_bg_restricted" /> <java-symbol type="integer" name="config_bg_current_drain_exempted_types" /> <java-symbol type="bool" name="config_bg_current_drain_high_threshold_by_bg_location" /> <java-symbol type="drawable" name="ic_swap_horiz" /> @@ -4773,4 +4778,6 @@ <java-symbol type="layout" name="app_language_picker_current_locale_item" /> <java-symbol type="id" name="system_locale_subtitle" /> <java-symbol type="id" name="language_picker_item" /> + + <java-symbol type="dimen" name="status_bar_height_default" /> </resources> diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java index e6d23643e8c0..f9f3b4c8ead1 100644 --- a/core/tests/coretests/src/android/app/NotificationTest.java +++ b/core/tests/coretests/src/android/app/NotificationTest.java @@ -17,6 +17,30 @@ package android.app; import static android.app.Notification.Builder.ensureColorSpanContrast; +import static android.app.Notification.CarExtender.UnreadConversation.KEY_ON_READ; +import static android.app.Notification.CarExtender.UnreadConversation.KEY_ON_REPLY; +import static android.app.Notification.CarExtender.UnreadConversation.KEY_REMOTE_INPUT; +import static android.app.Notification.EXTRA_ANSWER_INTENT; +import static android.app.Notification.EXTRA_BUILDER_APPLICATION_INFO; +import static android.app.Notification.EXTRA_CALL_PERSON; +import static android.app.Notification.EXTRA_CONVERSATION_ICON; +import static android.app.Notification.EXTRA_DECLINE_INTENT; +import static android.app.Notification.EXTRA_HANG_UP_INTENT; +import static android.app.Notification.EXTRA_LARGE_ICON; +import static android.app.Notification.EXTRA_LARGE_ICON_BIG; +import static android.app.Notification.EXTRA_MEDIA_REMOTE_INTENT; +import static android.app.Notification.EXTRA_MEDIA_SESSION; +import static android.app.Notification.EXTRA_MESSAGING_PERSON; +import static android.app.Notification.EXTRA_PICTURE; +import static android.app.Notification.EXTRA_PICTURE_ICON; +import static android.app.Notification.MessagingStyle.Message.KEY_DATA_URI; +import static android.app.Notification.MessagingStyle.Message.KEY_SENDER_PERSON; +import static android.app.Notification.MessagingStyle.Message.KEY_TEXT; +import static android.app.Notification.MessagingStyle.Message.KEY_TIMESTAMP; +import static android.app.Notification.TvExtender.EXTRA_CONTENT_INTENT; +import static android.app.Notification.TvExtender.EXTRA_DELETE_INTENT; +import static android.app.Notification.WearableExtender.KEY_BACKGROUND; +import static android.app.Notification.WearableExtender.KEY_DISPLAY_INTENT; import static com.android.compatibility.common.util.SystemUtil.runShellCommand; import static com.android.internal.util.ContrastColorUtilTest.assertContrastIsAtLeast; @@ -32,6 +56,7 @@ import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.spy; import android.annotation.Nullable; import android.content.Context; @@ -43,6 +68,7 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.drawable.Icon; +import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Parcel; @@ -170,7 +196,7 @@ public class NotificationTest { assertNotSame(q.getLargeIcon(), n.getLargeIcon()); assertTrue(q.getLargeIcon().getBitmap().sameAs(n.getLargeIcon().getBitmap())); - assertSame(q.getLargeIcon(), q.extras.getParcelable(Notification.EXTRA_LARGE_ICON)); + assertSame(q.getLargeIcon(), q.extras.getParcelable(EXTRA_LARGE_ICON)); } @Test @@ -179,12 +205,12 @@ public class NotificationTest { mContext.getResources(), com.android.frameworks.coretests.R.drawable.test128x96)); Notification n = new Notification.Builder(mContext).build(); - n.extras.putParcelable(Notification.EXTRA_LARGE_ICON, originalIcon); + n.extras.putParcelable(EXTRA_LARGE_ICON, originalIcon); assertSame(n.getLargeIcon(), null); Notification q = writeAndReadParcelable(n); assertSame(q.getLargeIcon(), null); - assertTrue(((Icon) q.extras.getParcelable(Notification.EXTRA_LARGE_ICON)).getBitmap() + assertTrue(((Icon) q.extras.getParcelable(EXTRA_LARGE_ICON)).getBitmap() .sameAs(originalIcon.getBitmap())); } @@ -521,6 +547,70 @@ public class NotificationTest { } @Test + public void testBuild_ensureMessagingUserIsNotTooBig_resizesIcon() { + Icon hugeIcon = Icon.createWithBitmap( + Bitmap.createBitmap(3000, 3000, Bitmap.Config.ARGB_8888)); + Icon hugeMessageAvatar = Icon.createWithBitmap( + Bitmap.createBitmap(3000, 3000, Bitmap.Config.ARGB_8888)); + Icon hugeHistoricMessageAvatar = Icon.createWithBitmap( + Bitmap.createBitmap(3000, 3000, Bitmap.Config.ARGB_8888)); + + Notification.MessagingStyle style = new Notification.MessagingStyle( + new Person.Builder().setIcon(hugeIcon).setName("A User").build()); + style.addMessage(new Notification.MessagingStyle.Message("A message", 123456, + new Person.Builder().setIcon(hugeMessageAvatar).setName("A Sender").build())); + style.addHistoricMessage(new Notification.MessagingStyle.Message("A message", 123456, + new Person.Builder().setIcon(hugeHistoricMessageAvatar).setName( + "A Historic Sender").build())); + Notification notification = new Notification.Builder(mContext, "Channel").setStyle( + style).build(); + + Bitmap personIcon = style.getUser().getIcon().getBitmap(); + assertThat(personIcon.getWidth()).isEqualTo( + mContext.getResources().getDimensionPixelSize( + R.dimen.notification_person_icon_max_size)); + assertThat(personIcon.getHeight()).isEqualTo( + mContext.getResources().getDimensionPixelSize( + R.dimen.notification_person_icon_max_size)); + + Bitmap avatarIcon = style.getMessages().get(0).getSenderPerson().getIcon().getBitmap(); + assertThat(avatarIcon.getWidth()).isEqualTo( + mContext.getResources().getDimensionPixelSize( + R.dimen.notification_person_icon_max_size)); + assertThat(avatarIcon.getHeight()).isEqualTo( + mContext.getResources().getDimensionPixelSize( + R.dimen.notification_person_icon_max_size)); + + Bitmap historicAvatarIcon = style.getHistoricMessages().get( + 0).getSenderPerson().getIcon().getBitmap(); + assertThat(historicAvatarIcon.getWidth()).isEqualTo( + mContext.getResources().getDimensionPixelSize( + R.dimen.notification_person_icon_max_size)); + assertThat(historicAvatarIcon.getHeight()).isEqualTo( + mContext.getResources().getDimensionPixelSize( + R.dimen.notification_person_icon_max_size)); + } + + @Test + public void testBuild_ensureMessagingShortcutIconIsNotTooBig_resizesIcon() { + Icon hugeIcon = Icon.createWithBitmap( + Bitmap.createBitmap(3000, 3000, Bitmap.Config.ARGB_8888)); + Notification.MessagingStyle style = new Notification.MessagingStyle( + new Person.Builder().setName("A User").build()).setShortcutIcon(hugeIcon); + + Notification notification = new Notification.Builder(mContext, "Channel").setStyle( + style).build(); + Bitmap shortcutIcon = style.getShortcutIcon().getBitmap(); + + assertThat(shortcutIcon.getWidth()).isEqualTo( + mContext.getResources().getDimensionPixelSize( + R.dimen.notification_small_icon_size)); + assertThat(shortcutIcon.getHeight()).isEqualTo( + mContext.getResources().getDimensionPixelSize( + R.dimen.notification_small_icon_size)); + } + + @Test public void testColors_ensureColors_dayMode_producesValidPalette() { Notification.Colors c = new Notification.Colors(); boolean colorized = false; @@ -577,7 +667,7 @@ public class NotificationTest { public void testIsMediaNotification_invalidSession_returnsFalse() { // Extra was set manually to an invalid type Bundle extras = new Bundle(); - extras.putParcelable(Notification.EXTRA_MEDIA_SESSION, new Intent()); + extras.putParcelable(EXTRA_MEDIA_SESSION, new Intent()); Notification.MediaStyle mediaStyle = new Notification.MediaStyle(); Notification notification = new Notification.Builder(mContext, "test id") .setStyle(mediaStyle) @@ -586,6 +676,7 @@ public class NotificationTest { assertFalse(notification.isMediaNotification()); } + @Test public void validateColorizedPaletteForColor(int rawColor) { Notification.Colors cDay = new Notification.Colors(); Notification.Colors cNight = new Notification.Colors(); @@ -617,6 +708,174 @@ public class NotificationTest { } } + @Test + public void testVisitUris_invalidExtra_noCrash() { + Notification n = new Notification.Builder(mContext, "test") + .setSmallIcon(0) + .build(); + Bundle fakeTypes = new Bundle(); + fakeTypes.putParcelable(EXTRA_LARGE_ICON_BIG, new Bundle()); + fakeTypes.putParcelable(EXTRA_PICTURE_ICON, new Bundle()); + fakeTypes.putParcelable(EXTRA_MESSAGING_PERSON, new Bundle()); + + Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class); + n.visitUris(visitor); + + // no crash, good + } + + @Test + public void testRecoverBuilder_invalidExtra_noCrash() { + Notification n = new Notification.Builder(mContext, "test") + .setSmallIcon(0) + .build(); + Bundle fakeTypes = new Bundle(); + fakeTypes.putParcelable(EXTRA_BUILDER_APPLICATION_INFO, new Bundle()); + + Notification.Builder.recoverBuilder(mContext, n); + + // no crash, good + } + + @Test + public void testIsMediaNotification_invalidExtra_noCrash() { + Notification n = new Notification.Builder(mContext, "test") + .setSmallIcon(0) + .setStyle(new Notification.MediaStyle()) + .build(); + Bundle fakeTypes = new Bundle(); + fakeTypes.putParcelable(EXTRA_MEDIA_SESSION, new Bundle()); + + n.isMediaNotification(); + + // no crash, good + } + + @Test + public void testRestoreFromExtras_BigText_invalidExtra_noCrash() { + Notification.Style style = new Notification.BigTextStyle(); + Bundle fakeTypes = new Bundle(); + fakeTypes.putParcelable(EXTRA_LARGE_ICON_BIG, new Bundle()); + + style.restoreFromExtras(fakeTypes); + + // no crash, good + } + + @Test + public void testRestoreFromExtras_Messaging_invalidExtra_noCrash() { + Notification.Style style = new Notification.MessagingStyle(); + Bundle fakeTypes = new Bundle(); + fakeTypes.putParcelable(EXTRA_MESSAGING_PERSON, new Bundle()); + fakeTypes.putParcelable(EXTRA_CONVERSATION_ICON, new Bundle()); + + style.restoreFromExtras(fakeTypes); + + // no crash, good + } + + @Test + public void testRestoreFromExtras_Media_invalidExtra_noCrash() { + Notification.Style style = new Notification.MediaStyle(); + Bundle fakeTypes = new Bundle(); + fakeTypes.putParcelable(EXTRA_MEDIA_SESSION, new Bundle()); + fakeTypes.putParcelable(EXTRA_MEDIA_REMOTE_INTENT, new Bundle()); + + style.restoreFromExtras(fakeTypes); + + // no crash, good + } + + @Test + public void testRestoreFromExtras_Call_invalidExtra_noCrash() { + Notification.Style style = new Notification.CallStyle(); + Bundle fakeTypes = new Bundle(); + fakeTypes.putParcelable(EXTRA_CALL_PERSON, new Bundle()); + fakeTypes.putParcelable(EXTRA_ANSWER_INTENT, new Bundle()); + fakeTypes.putParcelable(EXTRA_DECLINE_INTENT, new Bundle()); + fakeTypes.putParcelable(EXTRA_HANG_UP_INTENT, new Bundle()); + + style.restoreFromExtras(fakeTypes); + + // no crash, good + } + + @Test + public void testGetPictureIcon_invalidExtra_noCrash() { + Bundle fakeTypes = new Bundle(); + fakeTypes.putParcelable(EXTRA_PICTURE, new Bundle()); + fakeTypes.putParcelable(EXTRA_PICTURE_ICON, new Bundle()); + + Notification.BigPictureStyle.getPictureIcon(fakeTypes); + + // no crash, good + } + + @Test + public void testWearableExtender_invalidExtra_noCrash() { + Notification n = new Notification.Builder(mContext, "test") + .setSmallIcon(0) + .setStyle(new Notification.MediaStyle()) + .build(); + Bundle fakeTypes = new Bundle(); + fakeTypes.putParcelable(KEY_DISPLAY_INTENT, new Bundle()); + fakeTypes.putParcelable(KEY_BACKGROUND, new Bundle()); + Notification.WearableExtender extender = new Notification.WearableExtender(n); + + // no crash, good + } + + @Test + public void testCarExtender_invalidExtra_noCrash() { + Notification n = new Notification.Builder(mContext, "test") + .setSmallIcon(0) + .setStyle(new Notification.MediaStyle()) + .build(); + Bundle fakeTypes = new Bundle(); + fakeTypes.putParcelable(EXTRA_LARGE_ICON, new Bundle()); + Notification.CarExtender extender = new Notification.CarExtender(n); + + // no crash, good + } + + @Test + public void testTvExtender_invalidExtra_noCrash() { + Notification n = new Notification.Builder(mContext, "test") + .setSmallIcon(0) + .setStyle(new Notification.MediaStyle()) + .build(); + Bundle fakeTypes = new Bundle(); + fakeTypes.putParcelable(EXTRA_CONTENT_INTENT, new Bundle()); + fakeTypes.putParcelable(EXTRA_DELETE_INTENT, new Bundle()); + Notification.TvExtender extender = new Notification.TvExtender(n); + + // no crash, good + } + + @Test + public void testGetUnreadConversationFromBundle_invalidExtra_noCrash() { + Bundle fakeTypes = new Bundle(); + fakeTypes.putParcelable(KEY_ON_READ, new Bundle()); + fakeTypes.putParcelable(KEY_ON_REPLY, new Bundle()); + fakeTypes.putParcelable(KEY_REMOTE_INPUT, new Bundle()); + Notification.CarExtender.UnreadConversation.getUnreadConversationFromBundle(fakeTypes); + + // no crash, good + } + + @Test + public void testGetMessageFromBundle_invalidExtra_noCrash() { + Bundle fakeTypes = new Bundle(); + fakeTypes.putParcelable(KEY_SENDER_PERSON, new Bundle()); + fakeTypes.putString(KEY_TEXT, "text"); + fakeTypes.putLong(KEY_TIMESTAMP, 0); + fakeTypes.putParcelable(KEY_REMOTE_INPUT, new Bundle()); + fakeTypes.putParcelable(KEY_DATA_URI, new Bundle()); + Notification.MessagingStyle.Message.getMessageFromBundle(fakeTypes); + + // no crash, good + } + private void assertValid(Notification.Colors c) { // Assert that all colors are populated assertThat(c.getBackgroundColor()).isNotEqualTo(Notification.COLOR_INVALID); diff --git a/core/tests/coretests/src/android/os/IpcDataCacheTest.java b/core/tests/coretests/src/android/os/IpcDataCacheTest.java index fa7d7214d289..34712ce54e0f 100644 --- a/core/tests/coretests/src/android/os/IpcDataCacheTest.java +++ b/core/tests/coretests/src/android/os/IpcDataCacheTest.java @@ -53,6 +53,14 @@ public class IpcDataCacheTest { return value(x); } + // A single query but this can throw an exception. + boolean query(int x, boolean y) throws RemoteException { + if (y) { + throw new RemoteException(); + } + return query(x); + } + // Return the expected value of an input, without incrementing the query count. boolean value(int x) { return x % 3 == 0; @@ -138,6 +146,47 @@ public class IpcDataCacheTest { tester.verify(9); } + // This test is disabled pending an sepolicy change that allows any app to set the + // test property. + @Test + public void testRemoteCall() { + + // A stand-in for the binder. The test verifies that calls are passed through to + // this class properly. + ServerProxy tester = new ServerProxy(); + + // Create a cache that uses simple arithmetic to computer its values. + IpcDataCache.Config config = new IpcDataCache.Config(4, MODULE, API, "testCache2"); + IpcDataCache<Integer, Boolean> testCache = + new IpcDataCache<>(config, (x) -> tester.query(x, x % 10 == 9)); + + IpcDataCache.setTestMode(true); + testCache.testPropertyName(); + + tester.verify(0); + assertEquals(tester.value(3), testCache.query(3)); + tester.verify(1); + assertEquals(tester.value(3), testCache.query(3)); + tester.verify(2); + testCache.invalidateCache(); + assertEquals(tester.value(3), testCache.query(3)); + tester.verify(3); + assertEquals(tester.value(5), testCache.query(5)); + tester.verify(4); + assertEquals(tester.value(5), testCache.query(5)); + tester.verify(4); + assertEquals(tester.value(3), testCache.query(3)); + tester.verify(4); + + try { + testCache.query(9); + assertEquals(false, true); // The code should not reach this point. + } catch (RuntimeException e) { + assertEquals(e.getCause() instanceof RemoteException, true); + } + tester.verify(4); + } + @Test public void testDisableCache() { @@ -225,6 +274,17 @@ public class IpcDataCacheTest { testPropertyName(); } + TestCache(IpcDataCache.Config c) { + this(c, new TestQuery()); + } + + TestCache(IpcDataCache.Config c, TestQuery query) { + super(c, query); + mQuery = query; + setTestMode(true); + testPropertyName(); + } + int getRecomputeCount() { return mQuery.getRecomputeCount(); } @@ -309,4 +369,48 @@ public class IpcDataCacheTest { assertEquals("foo5", cache.query(5)); assertEquals(3, cache.getRecomputeCount()); } + + @Test + public void testConfig() { + IpcDataCache.Config a = new IpcDataCache.Config(8, MODULE, "apiA"); + TestCache ac = new TestCache(a); + assertEquals(8, a.maxEntries()); + assertEquals(MODULE, a.module()); + assertEquals("apiA", a.api()); + assertEquals("apiA", a.name()); + IpcDataCache.Config b = new IpcDataCache.Config(a, "apiB"); + TestCache bc = new TestCache(b); + assertEquals(8, b.maxEntries()); + assertEquals(MODULE, b.module()); + assertEquals("apiB", b.api()); + assertEquals("apiB", b.name()); + IpcDataCache.Config c = new IpcDataCache.Config(a, "apiC", "nameC"); + TestCache cc = new TestCache(c); + assertEquals(8, c.maxEntries()); + assertEquals(MODULE, c.module()); + assertEquals("apiC", c.api()); + assertEquals("nameC", c.name()); + IpcDataCache.Config d = a.child("nameD"); + TestCache dc = new TestCache(d); + assertEquals(8, d.maxEntries()); + assertEquals(MODULE, d.module()); + assertEquals("apiA", d.api()); + assertEquals("nameD", d.name()); + + a.disableForCurrentProcess(); + assertEquals(ac.isDisabled(), true); + assertEquals(bc.isDisabled(), false); + assertEquals(cc.isDisabled(), false); + assertEquals(dc.isDisabled(), false); + + a.disableAllForCurrentProcess(); + assertEquals(ac.isDisabled(), true); + assertEquals(bc.isDisabled(), false); + assertEquals(cc.isDisabled(), false); + assertEquals(dc.isDisabled(), true); + + IpcDataCache.Config e = a.child("nameE"); + TestCache ec = new TestCache(e); + assertEquals(ec.isDisabled(), true); + } } diff --git a/core/tests/coretests/src/android/service/quicksettings/TileServiceTest.java b/core/tests/coretests/src/android/service/quicksettings/TileServiceTest.java new file mode 100644 index 000000000000..d28eeffae742 --- /dev/null +++ b/core/tests/coretests/src/android/service/quicksettings/TileServiceTest.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.quicksettings; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Intent; +import android.os.Binder; +import android.os.IBinder; +import android.os.RemoteException; +import android.testing.TestableLooper; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidJUnit4.class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +public class TileServiceTest { + + @Mock + private IQSService.Stub mIQSService; + + private IBinder mTileToken; + private TileService mTileService; + private Tile mTile; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mTileToken = new Binder(); + when(mIQSService.asBinder()).thenCallRealMethod(); + when(mIQSService.queryLocalInterface(anyString())).thenReturn(mIQSService); + + mTile = new Tile(); + + mTileService = new TileService(); + } + + @Test + public void testErrorRetrievingTile_nullBinding() throws RemoteException { + Intent intent = new Intent(); + intent.putExtra(TileService.EXTRA_SERVICE, mIQSService); + intent.putExtra(TileService.EXTRA_TOKEN, mTileToken); + when(mIQSService.getTile(mTileToken)).thenThrow(new RemoteException()); + + IBinder result = mTileService.onBind(intent); + assertNull(result); + } + + @Test + public void testNullTile_doesntSendStartSuccessful() throws RemoteException { + Intent intent = new Intent(); + intent.putExtra(TileService.EXTRA_SERVICE, mIQSService); + intent.putExtra(TileService.EXTRA_TOKEN, mTileToken); + when(mIQSService.getTile(mTileToken)).thenReturn(null); + + IBinder result = mTileService.onBind(intent); + + assertNotNull(result); + verify(mIQSService, never()).onStartSuccessful(any()); + } + + @Test + public void testBindSuccessful() throws RemoteException { + Intent intent = new Intent(); + intent.putExtra(TileService.EXTRA_SERVICE, mIQSService); + intent.putExtra(TileService.EXTRA_TOKEN, mTileToken); + when(mIQSService.getTile(mTileToken)).thenReturn(mTile); + + IBinder result = mTileService.onBind(intent); + + assertNotNull(result); + verify(mIQSService).onStartSuccessful(mTileToken); + + mTile.updateTile(); + verify(mIQSService).updateQsTile(mTile, mTileToken); + } + +} diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java index bf8bb76891d7..be9da11057a2 100644 --- a/core/tests/coretests/src/android/view/InsetsStateTest.java +++ b/core/tests/coretests/src/android/view/InsetsStateTest.java @@ -217,7 +217,8 @@ public class InsetsStateTest { mState.getSource(ITYPE_CAPTION_BAR).setVisible(true); Insets visibleInsets = mState.calculateVisibleInsets( - new Rect(0, 0, 100, 400), SOFT_INPUT_ADJUST_NOTHING); + new Rect(0, 0, 100, 400), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, + SOFT_INPUT_ADJUST_NOTHING, 0 /* windowFlags */); assertEquals(Insets.of(0, 300, 0, 0), visibleInsets); } @@ -227,7 +228,8 @@ public class InsetsStateTest { mState.getSource(ITYPE_CAPTION_BAR).setVisible(true); Insets visibleInsets = mState.calculateVisibleInsets( - new Rect(0, 0, 150, 400), SOFT_INPUT_ADJUST_NOTHING); + new Rect(0, 0, 150, 400), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, + SOFT_INPUT_ADJUST_NOTHING, 0 /* windowFlags */); assertEquals(Insets.of(0, 300, 0, 0), visibleInsets); } @@ -414,7 +416,8 @@ public class InsetsStateTest { mState.getSource(ITYPE_BOTTOM_GESTURES).setFrame(new Rect(0, 100, 100, 300)); mState.getSource(ITYPE_BOTTOM_GESTURES).setVisible(true); Insets visibleInsets = mState.calculateVisibleInsets( - new Rect(0, 0, 100, 300), SOFT_INPUT_ADJUST_PAN); + new Rect(0, 0, 100, 300), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, + SOFT_INPUT_ADJUST_PAN, 0 /* windowFlags */); assertEquals(Insets.of(0, 100, 0, 100), visibleInsets); } @@ -429,11 +432,28 @@ public class InsetsStateTest { mState.getSource(ITYPE_BOTTOM_GESTURES).setFrame(new Rect(0, 100, 100, 300)); mState.getSource(ITYPE_BOTTOM_GESTURES).setVisible(true); Insets visibleInsets = mState.calculateVisibleInsets( - new Rect(0, 0, 100, 300), SOFT_INPUT_ADJUST_NOTHING); + new Rect(0, 0, 100, 300), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, + SOFT_INPUT_ADJUST_NOTHING, 0 /* windowFlags */); assertEquals(Insets.of(0, 100, 0, 0), visibleInsets); } @Test + public void testCalculateVisibleInsets_layoutNoLimits() { + mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100)); + mState.getSource(ITYPE_STATUS_BAR).setVisible(true); + mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300)); + mState.getSource(ITYPE_IME).setVisible(true); + + // Make sure bottom gestures are ignored + mState.getSource(ITYPE_BOTTOM_GESTURES).setFrame(new Rect(0, 100, 100, 300)); + mState.getSource(ITYPE_BOTTOM_GESTURES).setVisible(true); + Insets visibleInsets = mState.calculateVisibleInsets( + new Rect(0, 0, 100, 300), TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, + SOFT_INPUT_ADJUST_PAN, FLAG_LAYOUT_NO_LIMITS); + assertEquals(Insets.NONE, visibleInsets); + } + + @Test public void testCalculateUncontrollableInsets() { mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 200, 100)); mState.getSource(ITYPE_STATUS_BAR).setVisible(true); diff --git a/core/tests/coretests/src/android/view/WindowInfoTest.java b/core/tests/coretests/src/android/view/WindowInfoTest.java index 0a99b08f58ff..afc2c002db08 100644 --- a/core/tests/coretests/src/android/view/WindowInfoTest.java +++ b/core/tests/coretests/src/android/view/WindowInfoTest.java @@ -26,6 +26,7 @@ import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import android.app.ActivityTaskManager; +import android.graphics.Matrix; import android.os.IBinder; import android.os.Parcel; import android.platform.test.annotations.Presubmit; @@ -38,6 +39,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.util.ArrayList; +import java.util.Arrays; /** * Class for testing {@link WindowInfo}. @@ -94,6 +96,8 @@ public class WindowInfoTest { assertFalse(w.inPictureInPicture); assertFalse(w.hasFlagWatchOutsideTouch); assertTrue(w.regionInScreen.isEmpty()); + assertEquals(w.mTransformMatrix.length, 9); + assertTrue(w.mMagnificationSpec.isNop()); } @SmallTest @@ -117,6 +121,8 @@ public class WindowInfoTest { equality &= w1.parentToken == w2.parentToken; equality &= w1.activityToken == w2.activityToken; equality &= w1.regionInScreen.equals(w2.regionInScreen); + equality &= w1.mMagnificationSpec.equals(w2.mMagnificationSpec); + equality &= Arrays.equals(w1.mTransformMatrix, w2.mTransformMatrix); return equality; } @@ -136,5 +142,9 @@ public class WindowInfoTest { windowInfo.inPictureInPicture = true; windowInfo.hasFlagWatchOutsideTouch = true; windowInfo.regionInScreen.set(0, 0, 1080, 1080); + windowInfo.mMagnificationSpec.scale = 2.0f; + windowInfo.mMagnificationSpec.offsetX = 100f; + windowInfo.mMagnificationSpec.offsetY = 200f; + Matrix.IDENTITY_MATRIX.getValues(windowInfo.mTransformMatrix); } } diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index c21aa2dd7353..9b09616d4630 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -703,12 +703,6 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1427392850": { - "message": "WindowState: Setting back callback %s (priority: %d) (Client IWindow: %s). (WindowState: %s)", - "level": "DEBUG", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/WindowState.java" - }, "-1427184084": { "message": "addWindow: New client %s: window=%s Callers=%s", "level": "VERBOSE", @@ -859,6 +853,12 @@ "group": "WM_DEBUG_ANIM", "at": "com\/android\/server\/wm\/WindowState.java" }, + "-1277068810": { + "message": "startBackNavigation currentTask=%s, topRunningActivity=%s, callbackInfo=%s, currentFocus=%s", + "level": "DEBUG", + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" + }, "-1270731689": { "message": "Attempted to set replacing window on app token with no content %s", "level": "WARN", @@ -1099,12 +1099,6 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1010850753": { - "message": "No focused window, defaulting to top task's window", - "level": "WARN", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/BackNavigationController.java" - }, "-1009117329": { "message": "isFetchingAppTransitionSpecs=true", "level": "VERBOSE", @@ -3043,12 +3037,6 @@ "group": "WM_DEBUG_REMOTE_ANIMATIONS", "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "878005951": { - "message": "startBackNavigation task=%s, topRunningActivity=%s, callbackInfo=%s, currentFocus=%s", - "level": "DEBUG", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/BackNavigationController.java" - }, "892244061": { "message": "Waiting for drawn %s: removed=%b visible=%b mHasSurface=%b drawState=%d", "level": "INFO", @@ -3331,12 +3319,6 @@ "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "1172542963": { - "message": "onBackNavigationDone backType=%s, task=%s, prevTaskTopActivity=%s", - "level": "DEBUG", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/BackNavigationController.java" - }, "1175495463": { "message": "ImeContainer just became organized. Reparenting under parent. imeParentSurfaceControl=%s", "level": "INFO", @@ -3409,6 +3391,12 @@ "group": "WM_DEBUG_STARTING_WINDOW", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, + "1264179654": { + "message": "No focused window, defaulting to top current task's window", + "level": "WARN", + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" + }, "1270792394": { "message": "Resumed after relaunch %s", "level": "DEBUG", @@ -3427,6 +3415,12 @@ "group": "WM_DEBUG_FOCUS_LIGHT", "at": "com\/android\/server\/wm\/WindowState.java" }, + "1288920916": { + "message": "Error sending initial insets change to WindowContainer overlay", + "level": "ERROR", + "group": "WM_DEBUG_ANIM", + "at": "com\/android\/server\/wm\/WindowContainer.java" + }, "1305412562": { "message": "Report configuration: %s %s", "level": "VERBOSE", @@ -3853,6 +3847,12 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, + "1778919449": { + "message": "onBackNavigationDone backType=%s, task=%s, prevActivity=%s", + "level": "DEBUG", + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" + }, "1781673113": { "message": "onAnimationFinished(): targetRootTask=%s targetActivity=%s mRestoreTargetBehindRootTask=%s", "level": "DEBUG", diff --git a/data/keyboards/Vendor_0e6f_Product_f501.kl b/data/keyboards/Vendor_0e6f_Product_f501.kl new file mode 100644 index 000000000000..b46c005353b1 --- /dev/null +++ b/data/keyboards/Vendor_0e6f_Product_f501.kl @@ -0,0 +1,55 @@ +# Copyright (C) 2022 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# XBox-compatible USB Controller +# + +key 304 BUTTON_A +key 305 BUTTON_B +key 307 BUTTON_X +key 308 BUTTON_Y +key 310 BUTTON_L1 +key 311 BUTTON_R1 + +key 317 BUTTON_THUMBL +key 318 BUTTON_THUMBR + +# Left and right stick. +# The reported value for flat is 128 out of a range from -32767 to 32768, which is absurd. +# This confuses applications that rely on the flat value because the joystick actually +# settles in a flat range of +/- 4096 or so. +axis 0x00 X flat 4096 +axis 0x01 Y flat 4096 +axis 0x03 Z flat 4096 +axis 0x04 RZ flat 4096 + +# Triggers. +axis 0x02 LTRIGGER +axis 0x05 RTRIGGER + +# Hat. +axis 0x10 HAT_X +axis 0x11 HAT_Y + +# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt + +# Button labeled as "BACK" (left-pointing triangle) +key 314 BUTTON_SELECT + +# The branded "X" button in the center of the controller +key 316 BUTTON_MODE + +# Button labeled as "START" (right-pointing triangle) +key 315 BUTTON_START diff --git a/graphics/java/android/graphics/BLASTBufferQueue.java b/graphics/java/android/graphics/BLASTBufferQueue.java index 7f70e1cce6f5..4b723d1569c9 100644 --- a/graphics/java/android/graphics/BLASTBufferQueue.java +++ b/graphics/java/android/graphics/BLASTBufferQueue.java @@ -47,7 +47,7 @@ public final class BLASTBufferQueue { /** Create a new connection with the surface flinger. */ public BLASTBufferQueue(String name, SurfaceControl sc, int width, int height, @PixelFormat.Format int format) { - this(name, false /* updateDestinationFrame */); + this(name, true /* updateDestinationFrame */); update(sc, width, height, format); } diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java index 54bab4ad3780..ffd041f60e26 100644 --- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java +++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java @@ -1637,8 +1637,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu * Sets whether the keystore requires the screen to be unlocked before allowing decryption * using this key. If this is set to {@code true}, any attempt to decrypt or sign using this * key while the screen is locked will fail. A locked device requires a PIN, password, - * biometric, or other trusted factor to access. While the screen is locked, the key can - * still be used for encryption or signature verification. + * biometric, or other trusted factor to access. While the screen is locked, any associated + * public key can still be used (e.g for signature verification). */ @NonNull public Builder setUnlockedDeviceRequired(boolean unlockedDeviceRequired) { diff --git a/libs/WindowManager/Jetpack/src/TEST_MAPPING b/libs/WindowManager/Jetpack/src/TEST_MAPPING new file mode 100644 index 000000000000..eacfe2520a6a --- /dev/null +++ b/libs/WindowManager/Jetpack/src/TEST_MAPPING @@ -0,0 +1,32 @@ +{ + "presubmit": [ + { + "name": "WMJetpackUnitTests", + "options": [ + { + "include-annotation": "android.platform.test.annotations.Presubmit" + }, + { + "exclude-annotation": "androidx.test.filters.FlakyTest" + }, + { + "exclude-annotation": "org.junit.Ignore" + } + ] + }, + { + "name": "CtsWindowManagerJetpackTestCases", + "options": [ + { + "include-annotation": "android.platform.test.annotations.Presubmit" + }, + { + "exclude-annotation": "androidx.test.filters.FlakyTest" + }, + { + "exclude-annotation": "org.junit.Ignore" + } + ] + } + ] +}
\ No newline at end of file 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 01f5feb9b13e..e20cef2bec4e 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -16,6 +16,8 @@ package androidx.window.extensions.embedding; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; + import static androidx.window.extensions.embedding.SplitContainer.getFinishPrimaryWithSecondaryBehavior; import static androidx.window.extensions.embedding.SplitContainer.getFinishSecondaryWithPrimaryBehavior; import static androidx.window.extensions.embedding.SplitContainer.isStickyPlaceholderRule; @@ -58,7 +60,8 @@ import java.util.function.Consumer; public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmentCallback, ActivityEmbeddingComponent { - private final SplitPresenter mPresenter; + @VisibleForTesting + final SplitPresenter mPresenter; // Currently applied split configuration. private final List<EmbeddingRule> mSplitRules = new ArrayList<>(); @@ -93,7 +96,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen mSplitRules.clear(); mSplitRules.addAll(rules); for (int i = mTaskContainers.size() - 1; i >= 0; i--) { - updateAnimationOverride(mTaskContainers.keyAt(i)); + updateAnimationOverride(mTaskContainers.valueAt(i)); } } @@ -147,16 +150,39 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return; } + final WindowContainerTransaction wct = new WindowContainerTransaction(); + final boolean wasInPip = isInPictureInPicture(container); container.setInfo(taskFragmentInfo); + final boolean isInPip = isInPictureInPicture(container); // Check if there are no running activities - consider the container empty if there are no // non-finishing activities left. if (!taskFragmentInfo.hasRunningActivity()) { - // Do not finish the dependents if this TaskFragment was cleared due to launching - // activity in the Task. - final boolean shouldFinishDependent = - !taskFragmentInfo.isTaskClearedForReuse(); - mPresenter.cleanupContainer(container, shouldFinishDependent); - } + if (taskFragmentInfo.isTaskFragmentClearedForPip()) { + // Do not finish the dependents if the last activity is reparented to PiP. + // Instead, the original split should be cleanup, and the dependent may be expanded + // to fullscreen. + cleanupForEnterPip(wct, container); + mPresenter.cleanupContainer(container, false /* shouldFinishDependent */, wct); + } else { + // Do not finish the dependents if this TaskFragment was cleared due to launching + // activity in the Task. + final boolean shouldFinishDependent = !taskFragmentInfo.isTaskClearedForReuse(); + mPresenter.cleanupContainer(container, shouldFinishDependent, wct); + } + } else if (wasInPip && isInPip) { + // No update until exit PIP. + return; + } else if (isInPip) { + // Enter PIP. + // All overrides will be cleanup. + container.setLastRequestedBounds(null /* bounds */); + cleanupForEnterPip(wct, container); + } else if (wasInPip) { + // Exit PIP. + // Updates the presentation of the container. Expand or launch placeholder if needed. + updateContainer(wct, container); + } + mPresenter.applyTransaction(wct); updateCallbackIfNecessary(); } @@ -165,7 +191,15 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen final TaskFragmentContainer container = getContainer(taskFragmentInfo.getFragmentToken()); if (container != null) { // Cleanup if the TaskFragment vanished is not requested by the organizer. - mPresenter.cleanupContainer(container, true /* shouldFinishDependent */); + removeContainer(container); + // Make sure the top container is updated. + final TaskFragmentContainer newTopContainer = getTopActiveContainer( + container.getTaskId()); + if (newTopContainer != null) { + final WindowContainerTransaction wct = new WindowContainerTransaction(); + updateContainer(wct, newTopContainer); + mPresenter.applyTransaction(wct); + } updateCallbackIfNecessary(); } cleanupTaskFragment(taskFragmentInfo.getFragmentToken()); @@ -174,10 +208,13 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen @Override public void onTaskFragmentParentInfoChanged(@NonNull IBinder fragmentToken, @NonNull Configuration parentConfig) { - TaskFragmentContainer container = getContainer(fragmentToken); + final TaskFragmentContainer container = getContainer(fragmentToken); if (container != null) { - onTaskBoundsMayChange(container.getTaskId(), - parentConfig.windowConfiguration.getBounds()); + onTaskConfigurationChanged(container.getTaskId(), parentConfig); + if (isInPictureInPicture(parentConfig)) { + // No need to update presentation in PIP until the Task exit PIP. + return; + } mPresenter.updateContainer(container); updateCallbackIfNecessary(); } @@ -199,44 +236,70 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } } - private void onTaskBoundsMayChange(int taskId, @NonNull Rect taskBounds) { + private void onTaskConfigurationChanged(int taskId, @NonNull Configuration config) { final TaskContainer taskContainer = mTaskContainers.get(taskId); - if (taskContainer != null && !taskBounds.isEmpty() - && !taskContainer.mTaskBounds.equals(taskBounds)) { + if (taskContainer == null) { + return; + } + final boolean wasInPip = isInPictureInPicture(taskContainer.mConfiguration); + final boolean isInPIp = isInPictureInPicture(config); + taskContainer.mConfiguration = config; + + // We need to check the animation override when enter/exit PIP or has bounds changed. + boolean shouldUpdateAnimationOverride = wasInPip != isInPIp; + if (onTaskBoundsMayChange(taskContainer, config.windowConfiguration.getBounds()) + && !isInPIp) { + // We don't care the bounds change when it has already entered PIP. + shouldUpdateAnimationOverride = true; + } + if (shouldUpdateAnimationOverride) { + updateAnimationOverride(taskContainer); + } + } + + /** Returns {@code true} if the bounds is changed. */ + private boolean onTaskBoundsMayChange(@NonNull TaskContainer taskContainer, + @NonNull Rect taskBounds) { + if (!taskBounds.isEmpty() && !taskContainer.mTaskBounds.equals(taskBounds)) { taskContainer.mTaskBounds.set(taskBounds); - updateAnimationOverride(taskId); + return true; } + return false; } /** * Updates if we should override transition animation. We only want to override if the Task * bounds is large enough for at least one split rule. */ - private void updateAnimationOverride(int taskId) { - final TaskContainer taskContainer = mTaskContainers.get(taskId); - if (taskContainer == null || !taskContainer.isTaskBoundsInitialized()) { + private void updateAnimationOverride(@NonNull TaskContainer taskContainer) { + if (!taskContainer.isTaskBoundsInitialized()) { // We don't know about the Task bounds yet. return; } + // We only want to override if it supports split. + if (supportSplit(taskContainer)) { + mPresenter.startOverrideSplitAnimation(taskContainer.mTaskId); + } else { + mPresenter.stopOverrideSplitAnimation(taskContainer.mTaskId); + } + } + + private boolean supportSplit(@NonNull TaskContainer taskContainer) { + // No split inside PIP. + if (isInPictureInPicture(taskContainer.mConfiguration)) { + return false; + } // Check if the parent container bounds can support any split rule. - boolean supportSplit = false; for (EmbeddingRule rule : mSplitRules) { if (!(rule instanceof SplitRule)) { continue; } if (mPresenter.shouldShowSideBySide(taskContainer.mTaskBounds, (SplitRule) rule)) { - supportSplit = true; - break; + return true; } } - - // We only want to override if it supports split. - if (supportSplit) { - mPresenter.startOverrideSplitAnimation(taskId); - } else { - mPresenter.stopOverrideSplitAnimation(taskId); - } + return false; } void onActivityCreated(@NonNull Activity launchedActivity) { @@ -250,6 +313,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen */ // TODO(b/190433398): Break down into smaller functions. void handleActivityCreated(@NonNull Activity launchedActivity) { + if (isInPictureInPicture(launchedActivity)) { + // We don't embed activity when it is in PIP. + return; + } final List<EmbeddingRule> splitRules = getSplitRules(); final TaskFragmentContainer currentContainer = getContainerWithActivity( launchedActivity.getActivityToken()); @@ -324,6 +391,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } private void onActivityConfigurationChanged(@NonNull Activity activity) { + if (isInPictureInPicture(activity)) { + // We don't embed activity when it is in PIP. + return; + } final TaskFragmentContainer currentContainer = getContainerWithActivity( activity.getActivityToken()); @@ -365,9 +436,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } final TaskContainer taskContainer = mTaskContainers.get(taskId); taskContainer.mContainers.add(container); - if (activity != null && !taskContainer.isTaskBoundsInitialized()) { + if (activity != null && !taskContainer.isTaskBoundsInitialized() + && onTaskBoundsMayChange(taskContainer, + SplitPresenter.getTaskBoundsFromActivity(activity))) { // Initial check before any TaskFragment has appeared. - onTaskBoundsMayChange(taskId, SplitPresenter.getTaskBoundsFromActivity(activity)); + updateAnimationOverride(taskContainer); } return container; } @@ -389,6 +462,43 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen mTaskContainers.get(primaryContainer.getTaskId()).mSplitContainers.add(splitContainer); } + /** Cleanups all the dependencies when the TaskFragment is entering PIP. */ + private void cleanupForEnterPip(@NonNull WindowContainerTransaction wct, + @NonNull TaskFragmentContainer container) { + final int taskId = container.getTaskId(); + final TaskContainer taskContainer = mTaskContainers.get(taskId); + if (taskContainer == null) { + return; + } + final List<SplitContainer> splitsToRemove = new ArrayList<>(); + final Set<TaskFragmentContainer> containersToUpdate = new ArraySet<>(); + for (SplitContainer splitContainer : taskContainer.mSplitContainers) { + if (splitContainer.getPrimaryContainer() != container + && splitContainer.getSecondaryContainer() != container) { + continue; + } + splitsToRemove.add(splitContainer); + final TaskFragmentContainer splitTf = splitContainer.getPrimaryContainer() == container + ? splitContainer.getSecondaryContainer() + : splitContainer.getPrimaryContainer(); + containersToUpdate.add(splitTf); + // We don't want the PIP TaskFragment to be removed as a result of any of its dependents + // being removed. + splitTf.removeContainerToFinishOnExit(container); + if (container.getTopNonFinishingActivity() != null) { + splitTf.removeActivityToFinishOnExit(container.getTopNonFinishingActivity()); + } + } + container.resetDependencies(); + taskContainer.mSplitContainers.removeAll(splitsToRemove); + // If there is any TaskFragment split with the PIP TaskFragment, update their presentations + // since the split is dismissed. + // We don't want to close any of them even if they are dependencies of the PIP TaskFragment. + for (TaskFragmentContainer containerToUpdate : containersToUpdate) { + updateContainer(wct, containerToUpdate); + } + } + /** * Removes the container from bookkeeping records. */ @@ -406,6 +516,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen // TaskFragment there. taskContainer.mFinishedContainer.add(container.getTaskFragmentToken()); + // Cleanup any split references. final List<SplitContainer> containersToRemove = new ArrayList<>(); for (SplitContainer splitContainer : taskContainer.mSplitContainers) { if (container.equals(splitContainer.getSecondaryContainer()) @@ -414,6 +525,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } } taskContainer.mSplitContainers.removeAll(containersToRemove); + + // Cleanup any dependent references. + for (TaskFragmentContainer containerToUpdate : taskContainer.mContainers) { + containerToUpdate.removeContainerToFinishOnExit(container); + } } /** @@ -916,6 +1032,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return super.onStartActivity(who, intent, options); } final Activity launchingActivity = (Activity) who; + if (isInPictureInPicture(launchingActivity)) { + // We don't embed activity when it is in PIP. + return super.onStartActivity(who, intent, options); + } if (shouldExpand(null, intent, getSplitRules())) { setLaunchingInExpandedContainer(launchingActivity, options); @@ -1079,6 +1199,19 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return !pairRule.shouldClearTop(); } + private static boolean isInPictureInPicture(@NonNull Activity activity) { + return isInPictureInPicture(activity.getResources().getConfiguration()); + } + + private static boolean isInPictureInPicture(@NonNull TaskFragmentContainer tf) { + return isInPictureInPicture(tf.getInfo().getConfiguration()); + } + + private static boolean isInPictureInPicture(@Nullable Configuration configuration) { + return configuration != null + && configuration.windowConfiguration.getWindowingMode() == WINDOWING_MODE_PINNED; + } + /** Represents TaskFragments and split pairs below a Task. */ @VisibleForTesting static class TaskContainer { @@ -1095,6 +1228,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen final Set<IBinder> mFinishedContainer = new ArraySet<>(); /** Available window bounds of this Task. */ final Rect mTaskBounds = new Rect(); + /** Configuration of the Task. */ + @Nullable + Configuration mConfiguration; TaskContainer(int taskId) { mTaskId = taskId; diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java index e4d9edeb4c6e..1b49585ed7dc 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java @@ -65,7 +65,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { /** * Updates the presentation of the provided container. */ - void updateContainer(TaskFragmentContainer container) { + void updateContainer(@NonNull TaskFragmentContainer container) { final WindowContainerTransaction wct = new WindowContainerTransaction(); mController.updateContainer(wct, container); applyTransaction(wct); @@ -77,7 +77,16 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { */ void cleanupContainer(@NonNull TaskFragmentContainer container, boolean shouldFinishDependent) { final WindowContainerTransaction wct = new WindowContainerTransaction(); + cleanupContainer(container, shouldFinishDependent, wct); + applyTransaction(wct); + } + /** + * Deletes the specified container and all other associated and dependent containers in the same + * transaction. + */ + void cleanupContainer(@NonNull TaskFragmentContainer container, boolean shouldFinishDependent, + @NonNull WindowContainerTransaction wct) { container.finish(shouldFinishDependent, this, wct, mController); final TaskFragmentContainer newTopContainer = mController.getTopActiveContainer( @@ -85,8 +94,6 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { if (newTopContainer != null) { mController.updateContainer(wct, newTopContainer); } - - applyTransaction(wct); } /** diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java index 9a12669f078a..871f545d203a 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java @@ -192,6 +192,13 @@ class TaskFragmentContainer { } /** + * Removes a container that should be finished when this container is finished. + */ + void removeContainerToFinishOnExit(@NonNull TaskFragmentContainer containerToRemove) { + mContainersToFinishOnExit.remove(containerToRemove); + } + + /** * Adds an activity that should be finished when this container is finished. */ void addActivityToFinishOnExit(@NonNull Activity activityToFinish) { @@ -199,6 +206,19 @@ class TaskFragmentContainer { } /** + * Removes an activity that should be finished when this container is finished. + */ + void removeActivityToFinishOnExit(@NonNull Activity activityToRemove) { + mActivitiesToFinishOnExit.remove(activityToRemove); + } + + /** Removes all dependencies that should be finished when this container is finished. */ + void resetDependencies() { + mContainersToFinishOnExit.clear(); + mActivitiesToFinishOnExit.clear(); + } + + /** * Removes all activities that belong to this process and finishes other containers/activities * configured to finish together. */ @@ -237,7 +257,8 @@ class TaskFragmentContainer { // Finish dependent containers for (TaskFragmentContainer container : mContainersToFinishOnExit) { - if (controller.shouldRetainAssociatedContainer(this, container)) { + if (container.mIsFinished + || controller.shouldRetainAssociatedContainer(this, container)) { continue; } container.finish(true /* shouldFinishDependent */, presenter, @@ -247,18 +268,13 @@ class TaskFragmentContainer { // Finish associated activities for (Activity activity : mActivitiesToFinishOnExit) { - if (controller.shouldRetainAssociatedActivity(this, activity)) { + if (activity.isFinishing() + || controller.shouldRetainAssociatedActivity(this, activity)) { continue; } activity.finish(); } mActivitiesToFinishOnExit.clear(); - - // Finish activities that were being re-parented to this container. - for (Activity activity : mPendingAppearedActivities) { - activity.finish(); - } - mPendingAppearedActivities.clear(); } boolean isFinished() { diff --git a/libs/WindowManager/Jetpack/tests/unittest/Android.bp b/libs/WindowManager/Jetpack/tests/unittest/Android.bp index 212fbd0a6752..b6e743a2b7e1 100644 --- a/libs/WindowManager/Jetpack/tests/unittest/Android.bp +++ b/libs/WindowManager/Jetpack/tests/unittest/Android.bp @@ -23,6 +23,8 @@ package { android_test { name: "WMJetpackUnitTests", + // To make the test run via TEST_MAPPING + test_suites: ["device-tests"], srcs: [ "**/*.java", diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java index b6df876e1956..13a2c78d463e 100644 --- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java +++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java @@ -18,6 +18,8 @@ package androidx.window.extensions; import static com.google.common.truth.Truth.assertThat; +import android.platform.test.annotations.Presubmit; + import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; @@ -25,6 +27,13 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +/** + * Test class for {@link WindowExtensionsTest}. + * + * Build/Install/Run: + * atest WMJetpackUnitTests:WindowExtensionsTest + */ +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class WindowExtensionsTest { diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java index 26463c18b9a0..b06ce4c19d5c 100644 --- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java +++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java @@ -24,6 +24,8 @@ import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.never; +import android.platform.test.annotations.Presubmit; + import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; @@ -39,6 +41,7 @@ import org.mockito.MockitoAnnotations; * Build/Install/Run: * atest WMJetpackUnitTests:JetpackTaskFragmentOrganizerTest */ +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class JetpackTaskFragmentOrganizerTest { diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java index 120c7ebfe2da..72519dc6da5f 100644 --- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java +++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java @@ -17,11 +17,20 @@ package androidx.window.extensions.embedding; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.google.common.truth.Truth.assertWithMessage; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; + +import android.app.Activity; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.platform.test.annotations.Presubmit; +import android.window.TaskFragmentInfo; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; @@ -30,24 +39,39 @@ import androidx.window.extensions.embedding.SplitController.TaskContainer; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; /** * Test class for {@link SplitController}. * * Build/Install/Run: - * atest WMJetpackUnitTests:SplitController + * atest WMJetpackUnitTests:SplitControllerTest */ +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class SplitControllerTest { private static final int TASK_ID = 10; + @Mock + private Activity mActivity; + @Mock + private Resources mActivityResources; + @Mock + private TaskFragmentInfo mInfo; private SplitController mSplitController; + private SplitPresenter mSplitPresenter; @Before public void setUp() { + MockitoAnnotations.initMocks(this); mSplitController = new SplitController(); + mSplitPresenter = mSplitController.mPresenter; spyOn(mSplitController); + spyOn(mSplitPresenter); + doReturn(mActivityResources).when(mActivity).getResources(); + doReturn(new Configuration()).when(mActivityResources).getConfiguration(); } @Test @@ -80,4 +104,17 @@ public class SplitControllerTest { assertWithMessage("Must return null because tf1 has no running activity.") .that(mSplitController.getTopActiveContainer(TASK_ID)).isNull(); } + + @Test + public void testOnTaskFragmentVanished() { + final TaskFragmentContainer tf = mSplitController.newContainer(mActivity, TASK_ID); + doReturn(tf.getTaskFragmentToken()).when(mInfo).getFragmentToken(); + + // The TaskFragment has been removed in the server, we only need to cleanup the reference. + mSplitController.onTaskFragmentVanished(mInfo); + + verify(mSplitPresenter, never()).deleteTaskFragment(any(), any()); + verify(mSplitController).removeContainer(tf); + verify(mActivity, never()).finish(); + } } diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentAnimationControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentAnimationControllerTest.java index 7f88f4e7ff2e..af3ad70c04db 100644 --- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentAnimationControllerTest.java +++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentAnimationControllerTest.java @@ -21,6 +21,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.never; +import android.platform.test.annotations.Presubmit; import android.window.TaskFragmentOrganizer; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -38,6 +39,7 @@ import org.mockito.MockitoAnnotations; * Build/Install/Run: * atest WMJetpackUnitTests:TaskFragmentAnimationControllerTest */ +@Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class TaskFragmentAnimationControllerTest { diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java new file mode 100644 index 000000000000..97896c2c0a57 --- /dev/null +++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.window.extensions.embedding; + +import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; + +import android.app.Activity; +import android.platform.test.annotations.Presubmit; +import android.window.TaskFragmentInfo; +import android.window.WindowContainerTransaction; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.ArrayList; + +/** + * Test class for {@link TaskFragmentContainer}. + * + * Build/Install/Run: + * atest WMJetpackUnitTests:TaskFragmentContainerTest + */ +@Presubmit +@SmallTest +@RunWith(AndroidJUnit4.class) +public class TaskFragmentContainerTest { + private static final int TASK_ID = 10; + + @Mock + private SplitPresenter mPresenter; + @Mock + private SplitController mController; + @Mock + private Activity mActivity; + @Mock + private TaskFragmentInfo mInfo; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testFinish() { + final TaskFragmentContainer container = new TaskFragmentContainer(mActivity, TASK_ID); + final WindowContainerTransaction wct = new WindowContainerTransaction(); + + // Only remove the activity, but not clear the reference until appeared. + container.finish(true /* shouldFinishDependent */, mPresenter, wct, mController); + + verify(mActivity).finish(); + verify(mPresenter, never()).deleteTaskFragment(any(), any()); + verify(mController, never()).removeContainer(any()); + + // Calling twice should not finish activity again. + clearInvocations(mActivity); + container.finish(true /* shouldFinishDependent */, mPresenter, wct, mController); + + verify(mActivity, never()).finish(); + verify(mPresenter, never()).deleteTaskFragment(any(), any()); + verify(mController, never()).removeContainer(any()); + + // Remove all references after the container has appeared in server. + doReturn(new ArrayList<>()).when(mInfo).getActivities(); + container.setInfo(mInfo); + container.finish(true /* shouldFinishDependent */, mPresenter, wct, mController); + + verify(mActivity, never()).finish(); + verify(mPresenter).deleteTaskFragment(wct, container.getTaskFragmentToken()); + verify(mController).removeContainer(container); + } +} diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml index 3a1107939c9f..c5d945a982ef 100644 --- a/libs/WindowManager/Shell/res/values-de/strings.xml +++ b/libs/WindowManager/Shell/res/values-de/strings.xml @@ -20,7 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Schließen"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Maximieren"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Einstellungen"</string> - <string name="pip_phone_enter_split" msgid="7042877263880641911">"„Bildschirm teilen“ aktivieren"</string> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"„Geteilter Bildschirm“ aktivieren"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menü"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ist in Bild im Bild"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Wenn du nicht möchtest, dass <xliff:g id="NAME">%s</xliff:g> diese Funktion verwendet, tippe, um die Einstellungen zu öffnen und die Funktion zu deaktivieren."</string> @@ -31,7 +31,7 @@ <string name="accessibility_action_pip_resize" msgid="4623966104749543182">"Größe anpassen"</string> <string name="accessibility_action_pip_stash" msgid="4060775037619702641">"In Stash legen"</string> <string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Aus Stash entfernen"</string> - <string name="dock_forced_resizable" msgid="1749750436092293116">"Die App funktioniert unter Umständen bei geteiltem Bildschirmmodus nicht."</string> + <string name="dock_forced_resizable" msgid="1749750436092293116">"Die App funktioniert unter Umständen im Modus für geteilten Bildschirm nicht."</string> <string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Das Teilen des Bildschirms wird in dieser App nicht unterstützt."</string> <string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Die App funktioniert auf einem sekundären Display möglicherweise nicht."</string> <string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Die App unterstützt den Start auf sekundären Displays nicht."</string> diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml index 9e7257112c6c..761fb9ddeb2f 100644 --- a/libs/WindowManager/Shell/res/values-fa/strings.xml +++ b/libs/WindowManager/Shell/res/values-fa/strings.xml @@ -48,8 +48,8 @@ <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"تمامصفحه پایین"</string> <string name="one_handed_tutorial_title" msgid="4583241688067426350">"استفاده از حالت یکدستی"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"برای خارج شدن، از پایین صفحهنمایش تند بهطرف بالا بکشید یا در هر جایی از بالای برنامه که میخواهید ضربه بزنید"</string> - <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"آغاز «حالت تک حرکت»"</string> - <string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"خروج از «حالت تک حرکت»"</string> + <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"آغاز «حالت یکدستی»"</string> + <string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"خروج از «حالت یکدستی»"</string> <string name="bubbles_settings_button_description" msgid="1301286017420516912">"تنظیمات برای حبابکهای <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="bubble_overflow_button_content_description" msgid="8160974472718594382">"لبریزشده"</string> <string name="bubble_accessibility_action_add_back" msgid="1830101076853540953">"افزودن برگشت به پشته"</string> diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml index dd5416f2e398..7157ed088d30 100644 --- a/libs/WindowManager/Shell/res/values-it/strings.xml +++ b/libs/WindowManager/Shell/res/values-it/strings.xml @@ -46,10 +46,10 @@ <string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Schermata superiore al 50%"</string> <string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Schermata superiore al 30%"</string> <string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Schermata inferiore a schermo intero"</string> - <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Usare la modalità one-hand"</string> + <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Usare la modalità a una mano"</string> <string name="one_handed_tutorial_description" msgid="3486582858591353067">"Per uscire, scorri verso l\'alto dalla parte inferiore dello schermo oppure tocca un punto qualsiasi sopra l\'app"</string> - <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Avvia la modalità one-hand"</string> - <string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"Esci dalla modalità one-hand"</string> + <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Avvia la modalità a una mano"</string> + <string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"Esci dalla modalità a una mano"</string> <string name="bubbles_settings_button_description" msgid="1301286017420516912">"Impostazioni per bolle <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="bubble_overflow_button_content_description" msgid="8160974472718594382">"Altre"</string> <string name="bubble_accessibility_action_add_back" msgid="1830101076853540953">"Aggiungi di nuovo all\'elenco"</string> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java index 42ac19509693..cfd06243da3c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java @@ -301,7 +301,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont int backType = mBackNavigationInfo.getType(); RemoteAnimationTarget animationTarget = mBackNavigationInfo.getDepartingAnimationTarget(); - BackEvent backEvent = new BackEvent(0, 0, progress, swipeEdge, animationTarget); + BackEvent backEvent = new BackEvent( + event.getX(), event.getY(), progress, swipeEdge, animationTarget); IOnBackInvokedCallback targetCallback = null; if (shouldDispatchToLauncher(backType)) { targetCallback = mBackToLauncherCallback; 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 1a1cd5b27c53..5ef24133ca11 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 @@ -385,7 +385,9 @@ public class BubbleController { mMainExecutor.execute(() -> { int expandedId = INVALID_TASK_ID; if (mStackView != null && mStackView.getExpandedBubble() != null - && isStackExpanded() && !mStackView.isExpansionAnimating()) { + && isStackExpanded() + && !mStackView.isExpansionAnimating() + && !mStackView.isSwitchAnimating()) { expandedId = mStackView.getExpandedBubble().getTaskId(); } if (expandedId != INVALID_TASK_ID && expandedId != taskId) { @@ -1225,12 +1227,6 @@ public class BubbleController { mOverflowListener.applyUpdate(update); } - // Collapsing? Do this first before remaining steps. - if (update.expandedChanged && !update.expanded) { - mStackView.setExpanded(false); - mSysuiProxy.requestNotificationShadeTopUi(false, TAG); - } - // Do removals, if any. ArrayList<Pair<Bubble, Integer>> removedBubbles = new ArrayList<>(update.removedBubbles); @@ -1307,6 +1303,11 @@ public class BubbleController { mStackView.updateBubbleOrder(update.bubbles); } + if (update.expandedChanged && !update.expanded) { + mStackView.setExpanded(false); + mSysuiProxy.requestNotificationShadeTopUi(false, TAG); + } + if (update.selectionChanged && mStackView != null) { mStackView.setSelectedBubble(update.selectedBubble); if (update.selectedBubble != null) { 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 7af8cfafe749..a2b35fc9211a 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 @@ -112,6 +112,7 @@ public class BubbleExpandedView extends LinearLayout { private ShapeDrawable mRightPointer; private float mCornerRadius = 0f; private int mBackgroundColorFloating; + private boolean mUsingMaxHeight; @Nullable private Bubble mBubble; private PendingIntent mPendingIntent; @@ -621,6 +622,13 @@ public class BubbleExpandedView extends LinearLayout { return prevWasIntentBased != newIsIntentBased; } + /** + * Whether the bubble is using all available height to display or not. + */ + public boolean isUsingMaxHeight() { + return mUsingMaxHeight; + } + void updateHeight() { if (mExpandedViewContainerLocation == null) { return; @@ -632,6 +640,7 @@ public class BubbleExpandedView extends LinearLayout { float height = desiredHeight == MAX_HEIGHT ? maxHeight : Math.min(desiredHeight, maxHeight); + mUsingMaxHeight = height == maxHeight; FrameLayout.LayoutParams lp = mIsOverflow ? (FrameLayout.LayoutParams) mOverflowView.getLayoutParams() : (FrameLayout.LayoutParams) mTaskView.getLayoutParams(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java index 97e5ee3a35d3..7cfacbcc92f8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java @@ -329,6 +329,11 @@ public class BubblePositioner { : mBubbleSize; } + /** Size of the visible (non-overlapping) part of the pointer. */ + public int getPointerSize() { + return mPointerHeight - mPointerOverlap; + } + /** The maximum number of bubbles that can be displayed comfortably on screen. */ public int getMaxBubbles() { return mMaxBubbles; @@ -367,7 +372,7 @@ public class BubblePositioner { * padding is added. */ public int[] getExpandedViewContainerPadding(boolean onLeft, boolean isOverflow) { - final int pointerTotalHeight = mPointerHeight - mPointerOverlap; + final int pointerTotalHeight = getPointerSize(); final int expandedViewLargeScreenInsetFurthestEdge = getExpandedViewLargeScreenInsetFurthestEdge(isOverflow); if (mIsLargeScreen) { @@ -557,7 +562,7 @@ public class BubblePositioner { } if (showBubblesVertically() && mImeVisible) { - return new PointF(x, getExpandedBubbleYForIme(index, state.numberOfBubbles)); + return new PointF(x, getExpandedBubbleYForIme(index, state)); } return new PointF(x, y); } @@ -567,10 +572,10 @@ public class BubblePositioner { * is showing. * * @param index the index of the bubble in the stack. - * @param numberOfBubbles the total number of bubbles in the stack. + * @param state information about the stack state (# of bubbles, selected bubble). * @return y position of the bubble on-screen when the stack is expanded. */ - private float getExpandedBubbleYForIme(int index, int numberOfBubbles) { + private float getExpandedBubbleYForIme(int index, BubbleStackView.StackViewState state) { final float top = getAvailableRect().top + mExpandedViewPadding; if (!showBubblesVertically()) { // Showing horizontally: align to top @@ -578,10 +583,10 @@ public class BubblePositioner { } // Showing vertically: might need to translate the bubbles above the IME. - // Subtract spacing here to provide a margin between top of IME and bottom of bubble row. - final float bottomHeight = getImeHeight() + mInsets.bottom - (mSpacingBetweenBubbles * 2); + // Add spacing here to provide a margin between top of IME and bottom of bubble row. + final float bottomHeight = getImeHeight() + mInsets.bottom + (mSpacingBetweenBubbles * 2); final float bottomInset = mScreenRect.bottom - bottomHeight; - final float expandedStackSize = getExpandedStackSize(numberOfBubbles); + final float expandedStackSize = getExpandedStackSize(state.numberOfBubbles); final float centerPosition = mPositionRect.centerY(); final float rowBottom = centerPosition + (expandedStackSize / 2f); final float rowTop = centerPosition - (expandedStackSize / 2f); @@ -593,7 +598,7 @@ public class BubblePositioner { if (rowTop - translationY < top) { // Even if we shift the bubbles, they will still overlap with the IME. // Hide the overflow for a lil more space: - final float expandedStackSizeNoO = getExpandedStackSize(numberOfBubbles - 1); + final float expandedStackSizeNoO = getExpandedStackSize(state.numberOfBubbles - 1); final float centerPositionNoO = showBubblesVertically() ? mPositionRect.centerY() : mPositionRect.centerX(); @@ -603,6 +608,13 @@ public class BubblePositioner { rowTopForIme = rowTopNoO - translationY; } } + // Check if the selected bubble is within the appropriate space + final float selectedPosition = rowTopForIme + + (state.selectedIndex * (mBubbleSize + mSpacingBetweenBubbles)); + if (selectedPosition < top) { + // We must always keep the selected bubble in view so we'll have to allow more overlap. + rowTopForIme = top; + } return rowTopForIme + (index * (mBubbleSize + mSpacingBetweenBubbles)); } 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 a5998666b3f0..b7c5eb06fbfa 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 @@ -913,8 +913,10 @@ public class BubbleStackView extends FrameLayout afterExpandedViewAnimation(); showManageMenu(mShowingManage); } /* after */); + PointF p = mPositioner.getExpandedBubbleXY(getBubbleIndex(mExpandedBubble), + getState()); final float translationY = mPositioner.getExpandedViewY(mExpandedBubble, - getBubbleIndex(mExpandedBubble)); + mPositioner.showBubblesVertically() ? p.y : p.x); mExpandedViewContainer.setTranslationX(0f); mExpandedViewContainer.setTranslationY(translationY); mExpandedViewContainer.setAlpha(1f); @@ -1606,6 +1608,13 @@ public class BubbleStackView extends FrameLayout } /** + * Whether the stack of bubbles is animating a switch between bubbles. + */ + public boolean isSwitchAnimating() { + return mIsBubbleSwitchAnimating; + } + + /** * The {@link Bubble} that is expanded, null if one does not exist. */ @VisibleForTesting @@ -2355,7 +2364,14 @@ public class BubbleStackView extends FrameLayout } } else if (mPositioner.showBubblesVertically() && mIsExpanded && mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) { + float selectedY = mPositioner.getExpandedBubbleXY(getState().selectedIndex, + getState()).y; + float newExpandedViewTop = mPositioner.getExpandedViewY(mExpandedBubble, selectedY); mExpandedBubble.getExpandedView().setImeVisible(visible); + if (!mExpandedBubble.getExpandedView().isUsingMaxHeight()) { + mExpandedViewContainer.animate().translationY(newExpandedViewTop); + } + List<Animator> animList = new ArrayList(); for (int i = 0; i < mBubbleContainer.getChildCount(); i++) { View child = mBubbleContainer.getChildAt(i); @@ -2458,6 +2474,10 @@ public class BubbleStackView extends FrameLayout private void dismissBubbleIfExists(@Nullable BubbleViewProvider bubble) { if (bubble != null && mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) { + if (mIsExpanded && mBubbleData.getBubbles().size() > 1) { + // If we have more than 1 bubble we will perform the switch animation + mIsBubbleSwitchAnimating = true; + } mBubbleData.dismissBubbleWithKey(bubble.getKey(), Bubbles.DISMISS_USER_GESTURE); } } @@ -2878,7 +2898,10 @@ public class BubbleStackView extends FrameLayout PhysicsAnimator.getInstance(mAnimatingOutSurfaceContainer).cancel(); mAnimatingOutSurfaceContainer.setScaleX(1f); mAnimatingOutSurfaceContainer.setScaleY(1f); - mAnimatingOutSurfaceContainer.setTranslationX(mExpandedViewContainer.getPaddingLeft()); + final float translationX = mPositioner.showBubblesVertically() && mStackOnLeftOrWillBe + ? mExpandedViewContainer.getPaddingLeft() + mPositioner.getPointerSize() + : mExpandedViewContainer.getPaddingLeft(); + mAnimatingOutSurfaceContainer.setTranslationX(translationX); mAnimatingOutSurfaceContainer.setTranslationY(0); final int[] taskViewLocation = diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java index 6f4e22fa8a04..79d795ee613f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java @@ -32,6 +32,7 @@ import static android.view.Surface.ROTATION_90; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.ContentResolver; import android.content.Context; import android.content.res.Resources; @@ -336,6 +337,12 @@ public class DisplayLayout { return navigationBarPosition(res, mWidth, mHeight, mRotation); } + /** @return {@link DisplayCutout} instance. */ + @Nullable + public DisplayCutout getDisplayCutout() { + return mCutout; + } + /** * Calculates the stable insets if we already have the non-decor insets. */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java index 25fe8b9e0da3..ff3c0834cf62 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java @@ -94,6 +94,9 @@ public class DragLayout extends LinearLayout { mDividerSize = context.getResources().getDimensionPixelSize( R.dimen.split_divider_bar_width); + // Always use LTR because we assume dropZoneView1 is on the left and 2 is on the right when + // showing the highlight. + setLayoutDirection(LAYOUT_DIRECTION_LTR); mDropZoneView1 = new DropZoneView(context); mDropZoneView2 = new DropZoneView(context); addView(mDropZoneView1, new LinearLayout.LayoutParams(MATCH_PARENT, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java index 003c55977841..4bb580571145 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java @@ -40,7 +40,7 @@ import android.window.WindowContainerTransaction; import androidx.annotation.NonNull; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.policy.ForceShowNavigationBarSettingsObserver; +import com.android.internal.policy.KidsModeSettingsObserver; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayInsetsController; @@ -85,7 +85,7 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer { private int mDisplayWidth; private int mDisplayHeight; - private ForceShowNavigationBarSettingsObserver mForceShowNavigationBarSettingsObserver; + private KidsModeSettingsObserver mKidsModeSettingsObserver; private boolean mEnabled; DisplayController.OnDisplaysChangedListener mOnDisplaysChangedListener = @@ -138,14 +138,14 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer { DisplayController displayController, DisplayInsetsController displayInsetsController, Optional<RecentTasksController> recentTasks, - ForceShowNavigationBarSettingsObserver forceShowNavigationBarSettingsObserver) { + KidsModeSettingsObserver kidsModeSettingsObserver) { super(taskOrganizerController, mainExecutor, context, /* compatUI= */ null, recentTasks); mContext = context; mMainHandler = mainHandler; mSyncQueue = syncTransactionQueue; mDisplayController = displayController; mDisplayInsetsController = displayInsetsController; - mForceShowNavigationBarSettingsObserver = forceShowNavigationBarSettingsObserver; + mKidsModeSettingsObserver = kidsModeSettingsObserver; } public KidsModeTaskOrganizer( @@ -169,13 +169,13 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer { */ public void initialize(StartingWindowController startingWindowController) { initStartingWindow(startingWindowController); - if (mForceShowNavigationBarSettingsObserver == null) { - mForceShowNavigationBarSettingsObserver = new ForceShowNavigationBarSettingsObserver( + if (mKidsModeSettingsObserver == null) { + mKidsModeSettingsObserver = new KidsModeSettingsObserver( mMainHandler, mContext); } - mForceShowNavigationBarSettingsObserver.setOnChangeRunnable(() -> updateKidsModeState()); + mKidsModeSettingsObserver.setOnChangeRunnable(() -> updateKidsModeState()); updateKidsModeState(); - mForceShowNavigationBarSettingsObserver.register(); + mKidsModeSettingsObserver.register(); } @Override @@ -211,7 +211,7 @@ public class KidsModeTaskOrganizer extends ShellTaskOrganizer { @VisibleForTesting void updateKidsModeState() { - final boolean enabled = mForceShowNavigationBarSettingsObserver.isEnabled(); + final boolean enabled = mKidsModeSettingsObserver.isEnabled(); if (mEnabled == enabled) { return; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java index e28c58c2e7cd..9754a0369b67 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java @@ -37,7 +37,6 @@ import android.graphics.Region; import android.graphics.Region.Op; import android.hardware.display.DisplayManager; import android.os.Bundle; -import android.os.RemoteException; import android.util.AttributeSet; import android.util.Slog; import android.view.Choreographer; @@ -241,22 +240,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, } }; - private Runnable mUpdateEmbeddedMatrix = () -> { - if (getViewRootImpl() == null) { - return; - } - if (isHorizontalDivision()) { - mTmpMatrix.setTranslate(0, mDividerPositionY - mDividerInsets); - } else { - mTmpMatrix.setTranslate(mDividerPositionX - mDividerInsets, 0); - } - mTmpMatrix.getValues(mTmpValues); - try { - getViewRootImpl().getAccessibilityEmbeddedConnection().setScreenMatrix(mTmpValues); - } catch (RemoteException e) { - } - }; - public DividerView(Context context) { this(context, null); } @@ -1045,10 +1028,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, t.setPosition(dividerCtrl, mDividerPositionX - mDividerInsets, 0); } } - if (getViewRootImpl() != null) { - getHandler().removeCallbacks(mUpdateEmbeddedMatrix); - getHandler().post(mUpdateEmbeddedMatrix); - } } void setResizeDimLayer(Transaction t, boolean primary, float alpha) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java index 337900088c92..95bb65c5873e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java @@ -250,7 +250,6 @@ public class PipAnimationController { protected T mCurrentValue; protected T mStartValue; private T mEndValue; - private float mStartingAngle; private PipAnimationCallback mPipAnimationCallback; private PipTransactionHandler mPipTransactionHandler; private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory @@ -260,8 +259,8 @@ public class PipAnimationController { protected SurfaceControl mContentOverlay; private PipTransitionAnimator(TaskInfo taskInfo, SurfaceControl leash, - @AnimationType int animationType, Rect destinationBounds, T baseValue, T startValue, - T endValue, float startingAngle) { + @AnimationType int animationType, + Rect destinationBounds, T baseValue, T startValue, T endValue) { mTaskInfo = taskInfo; mLeash = leash; mAnimationType = animationType; @@ -269,7 +268,6 @@ public class PipAnimationController { mBaseValue = baseValue; mStartValue = startValue; mEndValue = endValue; - mStartingAngle = startingAngle; addListener(this); addUpdateListener(this); mSurfaceControlTransactionFactory = @@ -480,7 +478,7 @@ public class PipAnimationController { static PipTransitionAnimator<Float> ofAlpha(TaskInfo taskInfo, SurfaceControl leash, Rect destinationBounds, float startValue, float endValue) { return new PipTransitionAnimator<Float>(taskInfo, leash, ANIM_TYPE_ALPHA, - destinationBounds, startValue, startValue, endValue, 0) { + destinationBounds, startValue, startValue, endValue) { @Override void applySurfaceControlTransaction(SurfaceControl leash, SurfaceControl.Transaction tx, float fraction) { @@ -520,7 +518,7 @@ public class PipAnimationController { @PipAnimationController.TransitionDirection int direction, float startingAngle, @Surface.Rotation int rotationDelta) { final boolean isOutPipDirection = isOutPipDirection(direction); - + final boolean isInPipDirection = isInPipDirection(direction); // Just for simplicity we'll interpolate between the source rect hint insets and empty // insets to calculate the window crop final Rect initialSourceValue; @@ -559,8 +557,7 @@ public class PipAnimationController { // construct new Rect instances in case they are recycled return new PipTransitionAnimator<Rect>(taskInfo, leash, ANIM_TYPE_BOUNDS, - endValue, new Rect(baseValue), new Rect(startValue), new Rect(endValue), - startingAngle) { + endValue, new Rect(baseValue), new Rect(startValue), new Rect(endValue)) { private final RectEvaluator mRectEvaluator = new RectEvaluator(new Rect()); private final RectEvaluator mInsetsEvaluator = new RectEvaluator(new Rect()); @@ -595,7 +592,8 @@ public class PipAnimationController { } else { final Rect insets = computeInsets(fraction); getSurfaceTransactionHelper().scaleAndCrop(tx, leash, - initialSourceValue, bounds, insets); + sourceHintRect, initialSourceValue, bounds, insets, + isInPipDirection); if (shouldApplyCornerRadius()) { final Rect sourceBounds = new Rect(initialContainerRect); sourceBounds.inset(insets); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java index 00f62d435b68..b349010be1fe 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java @@ -103,21 +103,31 @@ public class PipSurfaceTransactionHelper { * @return same {@link PipSurfaceTransactionHelper} instance for method chaining */ public PipSurfaceTransactionHelper scaleAndCrop(SurfaceControl.Transaction tx, - SurfaceControl leash, - Rect sourceBounds, Rect destinationBounds, Rect insets) { + SurfaceControl leash, Rect sourceRectHint, + Rect sourceBounds, Rect destinationBounds, Rect insets, + boolean isInPipDirection) { mTmpSourceRectF.set(sourceBounds); mTmpDestinationRect.set(sourceBounds); mTmpDestinationRect.inset(insets); // Scale by the shortest edge and offset such that the top/left of the scaled inset source // rect aligns with the top/left of the destination bounds - final float scale = sourceBounds.width() <= sourceBounds.height() - ? (float) destinationBounds.width() / sourceBounds.width() - : (float) destinationBounds.height() / sourceBounds.height(); + final float scale; + if (isInPipDirection + && sourceRectHint != null && sourceRectHint.width() < sourceBounds.width()) { + // scale by sourceRectHint if it's not edge-to-edge, for entering PiP transition only. + scale = sourceBounds.width() <= sourceBounds.height() + ? (float) destinationBounds.width() / sourceRectHint.width() + : (float) destinationBounds.height() / sourceRectHint.height(); + } else { + scale = sourceBounds.width() <= sourceBounds.height() + ? (float) destinationBounds.width() / sourceBounds.width() + : (float) destinationBounds.height() / sourceBounds.height(); + } final float left = destinationBounds.left - insets.left * scale; final float top = destinationBounds.top - insets.top * scale; mTmpTransform.setScale(scale, scale); tx.setMatrix(leash, mTmpTransform, mTmpFloat9) - .setWindowCrop(leash, mTmpDestinationRect) + .setCrop(leash, mTmpDestinationRect) .setPosition(leash, left, top); return this; } @@ -163,7 +173,7 @@ public class PipSurfaceTransactionHelper { mTmpTransform.setScale(scale, scale); mTmpTransform.postRotate(degrees); mTmpTransform.postTranslate(positionX, positionY); - tx.setMatrix(leash, mTmpTransform, mTmpFloat9).setWindowCrop(leash, crop); + tx.setMatrix(leash, mTmpTransform, mTmpFloat9).setCrop(leash, crop); return this; } 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 b6635f3b8dd7..9dc861c72510 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 @@ -924,6 +924,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, removeContentOverlay(mSwipePipToHomeOverlay, null /* callback */); mSwipePipToHomeOverlay = null; } + resetShadowRadius(); mPipTransitionState.setInSwipePipToHomeTransition(false); mPictureInPictureParams = null; mPipTransitionState.setTransitionState(PipTransitionState.UNDEFINED); @@ -1569,13 +1570,28 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, // Avoid double removal, which is fatal. return; } - final SurfaceControl.Transaction tx = - mSurfaceControlTransactionFactory.getTransaction(); + final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction(); tx.remove(surface); tx.apply(); if (callback != null) callback.run(); } + private void resetShadowRadius() { + if (mPipTransitionState.getTransitionState() == PipTransitionState.UNDEFINED) { + // mLeash is undefined when in PipTransitionState.UNDEFINED + return; + } + final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction(); + tx.setShadowRadius(mLeash, 0f); + tx.apply(); + } + + @VisibleForTesting + public void setSurfaceControlTransactionFactory( + PipSurfaceTransactionHelper.SurfaceControlTransactionFactory factory) { + mSurfaceControlTransactionFactory = factory; + } + /** * Dumps internal states. */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java index 5e4c12ed37ed..f73b81e9d3f3 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java @@ -135,19 +135,6 @@ public class PhonePipMenuController implements PipMenuController { } }; - private final float[] mTmpValues = new float[9]; - private final Runnable mUpdateEmbeddedMatrix = () -> { - if (mPipMenuView == null || mPipMenuView.getViewRootImpl() == null) { - return; - } - mMoveTransform.getValues(mTmpValues); - try { - mPipMenuView.getViewRootImpl().getAccessibilityEmbeddedConnection() - .setScreenMatrix(mTmpValues); - } catch (RemoteException e) { - } - }; - public PhonePipMenuController(Context context, PipBoundsState pipBoundsState, PipMediaController mediaController, SystemWindows systemWindows, Optional<SplitScreenController> splitScreenOptional, @@ -348,11 +335,6 @@ public class PhonePipMenuController implements PipMenuController { } else { mApplier.scheduleApply(params); } - - if (mPipMenuView.getViewRootImpl() != null) { - mPipMenuView.getHandler().removeCallbacks(mUpdateEmbeddedMatrix); - mPipMenuView.getHandler().post(mUpdateEmbeddedMatrix); - } } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipAccessibilityInteractionConnection.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipAccessibilityInteractionConnection.java index 69ae45d12795..7365b9525919 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipAccessibilityInteractionConnection.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipAccessibilityInteractionConnection.java @@ -285,7 +285,7 @@ public class PipAccessibilityInteractionConnection { Region bounds, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, long interrogatingTid, MagnificationSpec spec, - Bundle arguments) throws RemoteException { + float[] matrixValues, Bundle arguments) throws RemoteException { mMainExcutor.execute(() -> { PipAccessibilityInteractionConnection.this .findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId, bounds, @@ -298,7 +298,8 @@ public class PipAccessibilityInteractionConnection { public void findAccessibilityNodeInfosByViewId(long accessibilityNodeId, String viewId, Region bounds, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, - int interrogatingPid, long interrogatingTid, MagnificationSpec spec) + int interrogatingPid, long interrogatingTid, MagnificationSpec spec, + float[] matrixValues) throws RemoteException { mMainExcutor.execute(() -> { PipAccessibilityInteractionConnection.this.findAccessibilityNodeInfosByViewId( @@ -311,7 +312,8 @@ public class PipAccessibilityInteractionConnection { public void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text, Region bounds, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, - int interrogatingPid, long interrogatingTid, MagnificationSpec spec) + int interrogatingPid, long interrogatingTid, MagnificationSpec spec, + float[] matrixValues) throws RemoteException { mMainExcutor.execute(() -> { PipAccessibilityInteractionConnection.this.findAccessibilityNodeInfosByText( @@ -323,7 +325,8 @@ public class PipAccessibilityInteractionConnection { @Override public void findFocus(long accessibilityNodeId, int focusType, Region bounds, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, - int interrogatingPid, long interrogatingTid, MagnificationSpec spec) + int interrogatingPid, long interrogatingTid, MagnificationSpec spec, + float[] matrixValues) throws RemoteException { mMainExcutor.execute(() -> { PipAccessibilityInteractionConnection.this.findFocus(accessibilityNodeId, focusType, @@ -335,7 +338,8 @@ public class PipAccessibilityInteractionConnection { @Override public void focusSearch(long accessibilityNodeId, int direction, Region bounds, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, - int interrogatingPid, long interrogatingTid, MagnificationSpec spec) + int interrogatingPid, long interrogatingTid, MagnificationSpec spec, + float[] matrixValues) throws RemoteException { mMainExcutor.execute(() -> { PipAccessibilityInteractionConnection.this.focusSearch(accessibilityNodeId, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java index 147a272f4645..ac7b9033b2b9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java @@ -36,6 +36,7 @@ import android.graphics.PointF; import android.graphics.Rect; import android.provider.DeviceConfig; import android.util.Size; +import android.view.DisplayCutout; import android.view.InputEvent; import android.view.MotionEvent; import android.view.ViewConfiguration; @@ -959,21 +960,38 @@ public class PipTouchHandler { } private boolean shouldStash(PointF vel, Rect motionBounds) { + final boolean flingToLeft = vel.x < -mStashVelocityThreshold; + final boolean flingToRight = vel.x > mStashVelocityThreshold; + final int offset = motionBounds.width() / 2; + final boolean droppingOnLeft = + motionBounds.left < mPipBoundsState.getDisplayBounds().left - offset; + final boolean droppingOnRight = + motionBounds.right > mPipBoundsState.getDisplayBounds().right + offset; + + // Do not allow stash if the destination edge contains display cutout. We only + // compare the left and right edges since we do not allow stash on top / bottom. + final DisplayCutout displayCutout = + mPipBoundsState.getDisplayLayout().getDisplayCutout(); + if (displayCutout != null) { + if ((flingToLeft || droppingOnLeft) + && !displayCutout.getBoundingRectLeft().isEmpty()) { + return false; + } else if ((flingToRight || droppingOnRight) + && !displayCutout.getBoundingRectRight().isEmpty()) { + return false; + } + } + // If user flings the PIP window above the minimum velocity, stash PIP. // Only allow stashing to the edge if PIP wasn't previously stashed on the opposite // edge. - final boolean stashFromFlingToEdge = ((vel.x < -mStashVelocityThreshold - && mPipBoundsState.getStashedState() != STASH_TYPE_RIGHT) - || (vel.x > mStashVelocityThreshold - && mPipBoundsState.getStashedState() != STASH_TYPE_LEFT)); + final boolean stashFromFlingToEdge = + (flingToLeft && mPipBoundsState.getStashedState() != STASH_TYPE_RIGHT) + || (flingToRight && mPipBoundsState.getStashedState() != STASH_TYPE_LEFT); // If User releases the PIP window while it's out of the display bounds, put // PIP into stashed mode. - final int offset = motionBounds.width() / 2; - final boolean stashFromDroppingOnEdge = - (motionBounds.right > mPipBoundsState.getDisplayBounds().right + offset - || motionBounds.left - < mPipBoundsState.getDisplayBounds().left - offset); + final boolean stashFromDroppingOnEdge = droppingOnLeft || droppingOnRight; return stashFromFlingToEdge || stashFromDroppingOnEdge; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsState.java index ea074993bae1..a3048bd8fabe 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsState.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsState.java @@ -35,7 +35,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** - * TV specific values of the current state of the PIP bounds. + * TV specific values of the current state of the PiP bounds. */ public class TvPipBoundsState extends PipBoundsState { @@ -86,7 +86,7 @@ public class TvPipBoundsState extends PipBoundsState { mTvPipGravity = DEFAULT_TV_GRAVITY; } - /** Set the tv expanded bounds of PIP */ + /** Set the tv expanded bounds of PiP */ public void setTvExpandedSize(@Nullable Size size) { mTvExpandedSize = size; } @@ -97,20 +97,24 @@ public class TvPipBoundsState extends PipBoundsState { return mTvExpandedSize; } - /** Set the PIP aspect ratio for the expanded PIP (TV) that is desired by the app. */ + /** Set the PiP aspect ratio for the expanded PiP (TV) that is desired by the app. */ public void setDesiredTvExpandedAspectRatio(float aspectRatio, boolean override) { - if (override || mTvFixedPipOrientation == ORIENTATION_UNDETERMINED || aspectRatio == 0) { + if (override || mTvFixedPipOrientation == ORIENTATION_UNDETERMINED) { mDesiredTvExpandedAspectRatio = aspectRatio; resetTvPipState(); return; } if ((aspectRatio > 1 && mTvFixedPipOrientation == ORIENTATION_HORIZONTAL) - || (aspectRatio <= 1 && mTvFixedPipOrientation == ORIENTATION_VERTICAL)) { + || (aspectRatio <= 1 && mTvFixedPipOrientation == ORIENTATION_VERTICAL) + || aspectRatio == 0) { mDesiredTvExpandedAspectRatio = aspectRatio; } } - /** Get the PIP aspect ratio for the expanded PIP (TV) that is desired by the app. */ + /** + * Get the aspect ratio for the expanded PiP (TV) that is desired, or {@code 0} if it is not + * enabled by the app. + */ public float getDesiredTvExpandedAspectRatio() { return mDesiredTvExpandedAspectRatio; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipKeepClearAlgorithm.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipKeepClearAlgorithm.kt index 4e8e71bd04c4..09d202abfbde 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipKeepClearAlgorithm.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipKeepClearAlgorithm.kt @@ -133,7 +133,8 @@ class TvPipKeepClearAlgorithm(private val clock: () -> Long) { val pipAnchorBoundsWithAllDecors = getNormalPipAnchorBounds(pipSizeWithAllDecors, transformedMovementBounds) - val pipAnchorBoundsWithPermanentDecors = removeTemporaryDecors(pipAnchorBoundsWithAllDecors) + val pipAnchorBoundsWithPermanentDecors = + removeTemporaryDecorsTransformed(pipAnchorBoundsWithAllDecors) val result = calculatePipPositionTransformed( pipAnchorBoundsWithPermanentDecors, transformedRestrictedAreas, @@ -471,12 +472,10 @@ class TvPipKeepClearAlgorithm(private val clock: () -> Long) { } fun setPipPermanentDecorInsets(insets: Insets) { - if (pipPermanentDecorInsets == insets) return pipPermanentDecorInsets = insets } fun setPipTemporaryDecorInsets(insets: Insets) { - if (pipTemporaryDecorInsets == insets) return pipTemporaryDecorInsets = insets } @@ -781,6 +780,7 @@ class TvPipKeepClearAlgorithm(private val clock: () -> Long) { /** * Removes the space that was reserved for permanent decorations around the pip + * @param bounds the bounds (in screen space) to remove the insets from */ private fun removePermanentDecors(bounds: Rect): Rect { val pipDecorReverseInsets = Insets.subtract(Insets.NONE, pipPermanentDecorInsets) @@ -790,11 +790,15 @@ class TvPipKeepClearAlgorithm(private val clock: () -> Long) { /** * Removes the space that was reserved for temporary decorations around the pip + * @param bounds the bounds (in base case) to remove the insets from */ - private fun removeTemporaryDecors(bounds: Rect): Rect { - val pipDecorReverseInsets = Insets.subtract(Insets.NONE, pipTemporaryDecorInsets) - bounds.inset(pipDecorReverseInsets) - return bounds + private fun removeTemporaryDecorsTransformed(bounds: Rect): Rect { + if (pipTemporaryDecorInsets == Insets.NONE) return bounds + + var reverseInsets = Insets.subtract(Insets.NONE, pipTemporaryDecorInsets) + var boundsInScreenSpace = fromTransformedSpace(bounds) + boundsInScreenSpace.inset(reverseInsets) + return toTransformedSpace(boundsInScreenSpace) } private fun Rect.offsetCopy(dx: Int, dy: Int) = Rect(this).apply { offset(dx, dy) } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java index 7b8dcf70cff0..2d67254f3610 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuController.java @@ -30,7 +30,6 @@ import android.graphics.Matrix; import android.graphics.Rect; import android.graphics.RectF; import android.os.Handler; -import android.os.RemoteException; import android.view.LayoutInflater; import android.view.SurfaceControl; import android.view.SyncRtSurfaceTransactionApplier; @@ -88,19 +87,6 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis RectF mTmpDestinationRectF = new RectF(); Matrix mMoveTransform = new Matrix(); - private final float[] mTmpValues = new float[9]; - private final Runnable mUpdateEmbeddedMatrix = () -> { - if (mPipMenuView == null || mPipMenuView.getViewRootImpl() == null) { - return; - } - mMoveTransform.getValues(mTmpValues); - try { - mPipMenuView.getViewRootImpl().getAccessibilityEmbeddedConnection() - .setScreenMatrix(mTmpValues); - } catch (RemoteException e) { - if (DEBUG) e.printStackTrace(); - } - }; private final Runnable mCloseEduTextRunnable = this::closeEduText; public TvPipMenuController(Context context, TvPipBoundsState tvPipBoundsState, @@ -525,11 +511,6 @@ public class TvPipMenuController implements PipMenuController, TvPipMenuView.Lis mApplier.scheduleApply(frontParams); } - if (mPipMenuView.getViewRootImpl() != null) { - mPipMenuView.getHandler().removeCallbacks(mUpdateEmbeddedMatrix); - mPipMenuView.getHandler().post(mUpdateEmbeddedMatrix); - } - updateMenuBounds(pipDestBounds); } 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 aec51baa4af7..dd2634ca36d9 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 @@ -190,7 +190,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, mStageCoordinator = new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue, mTaskOrganizer, mDisplayController, mDisplayImeController, mDisplayInsetsController, mTransitions, mTransactionPool, mLogger, - mIconProvider, mRecentTasksOptional, mUnfoldControllerProvider); + mIconProvider, mMainExecutor, mRecentTasksOptional, mUnfoldControllerProvider); } } @@ -414,7 +414,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } RemoteAnimationTarget[] onGoingToRecentsLegacy(boolean cancel, RemoteAnimationTarget[] apps) { - if (ENABLE_SHELL_TRANSITIONS || apps.length < 2) return null; + if (ENABLE_SHELL_TRANSITIONS || !isSplitScreenVisible()) return null; // TODO(b/206487881): Integrate this with shell transition. SurfaceControl.Transaction transaction = new SurfaceControl.Transaction(); if (mSplitTasksContainerLayer != null) { 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 45931de5e35e..9d6e34ddd9d7 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 @@ -94,6 +94,7 @@ import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.DisplayLayout; +import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.common.split.SplitLayout; @@ -157,6 +158,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, private final TransactionPool mTransactionPool; private final SplitScreenTransitions mSplitTransitions; private final SplitscreenEventLogger mLogger; + private final ShellExecutor mMainExecutor; private final Optional<RecentTasksController> mRecentTasks; /** @@ -196,13 +198,15 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, DisplayImeController displayImeController, DisplayInsetsController displayInsetsController, Transitions transitions, TransactionPool transactionPool, SplitscreenEventLogger logger, - IconProvider iconProvider, Optional<RecentTasksController> recentTasks, + IconProvider iconProvider, ShellExecutor mainExecutor, + Optional<RecentTasksController> recentTasks, Provider<Optional<StageTaskUnfoldController>> unfoldControllerProvider) { mContext = context; mDisplayId = displayId; mSyncQueue = syncQueue; mTaskOrganizer = taskOrganizer; mLogger = logger; + mMainExecutor = mainExecutor; mRecentTasks = recentTasks; mMainUnfoldController = unfoldControllerProvider.get().orElse(null); mSideUnfoldController = unfoldControllerProvider.get().orElse(null); @@ -247,7 +251,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, DisplayController displayController, DisplayImeController displayImeController, DisplayInsetsController displayInsetsController, SplitLayout splitLayout, Transitions transitions, TransactionPool transactionPool, - SplitscreenEventLogger logger, + SplitscreenEventLogger logger, ShellExecutor mainExecutor, Optional<RecentTasksController> recentTasks, Provider<Optional<StageTaskUnfoldController>> unfoldControllerProvider) { mContext = context; @@ -266,6 +270,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, mMainUnfoldController = unfoldControllerProvider.get().orElse(null); mSideUnfoldController = unfoldControllerProvider.get().orElse(null); mLogger = logger; + mMainExecutor = mainExecutor; mRecentTasks = recentTasks; mDisplayController.addDisplayWindowListener(this); mDisplayLayout = new DisplayLayout(); @@ -394,6 +399,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, @Nullable PendingIntent pendingIntent, @Nullable Intent fillInIntent, @Nullable Bundle mainOptions, @Nullable Bundle sideOptions, @SplitPosition int sidePosition, float splitRatio, RemoteAnimationAdapter adapter) { + final boolean withIntent = pendingIntent != null && fillInIntent != null; // Init divider first to make divider leash for remote animation target. mSplitLayout.init(); // Set false to avoid record new bounds with old task still on top; @@ -423,10 +429,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, new IRemoteAnimationFinishedCallback.Stub() { @Override public void onAnimationFinished() throws RemoteException { - mIsDividerRemoteAnimating = false; - mShouldUpdateRecents = true; - mSyncQueue.queue(evictWct); - mSyncQueue.runInSync(t -> setDividerVisibility(true, t)); + onRemoteAnimationFinishedOrCancelled(evictWct); finishedCallback.onAnimationFinished(); } }; @@ -447,10 +450,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, @Override public void onAnimationCancelled() { - mIsDividerRemoteAnimating = false; - mShouldUpdateRecents = true; - mSyncQueue.queue(evictWct); - mSyncQueue.runInSync(t -> setDividerVisibility(true, t)); + onRemoteAnimationFinishedOrCancelled(evictWct); try { adapter.getRunner().onAnimationCancelled(); } catch (RemoteException e) { @@ -486,20 +486,37 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, addActivityOptions(sideOptions, mSideStage); // Add task launch requests - if (pendingIntent != null && fillInIntent != null) { - wct.startTask(mainTaskId, mainOptions); + wct.startTask(mainTaskId, mainOptions); + if (withIntent) { wct.sendPendingIntent(pendingIntent, fillInIntent, sideOptions); } else { - wct.startTask(mainTaskId, mainOptions); wct.startTask(sideTaskId, sideOptions); } - // Using legacy transitions, so we can't use blast sync since it conflicts. mTaskOrganizer.applyTransaction(wct); mSyncQueue.runInSync(t -> updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */)); } + private void onRemoteAnimationFinishedOrCancelled(WindowContainerTransaction evictWct) { + mIsDividerRemoteAnimating = false; + mShouldUpdateRecents = true; + // If any stage has no child after animation finished, it means that split will display + // nothing, such status will happen if task and intent is same app but not support + // multi-instagce, we should exit split and expand that app as full screen. + if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) { + mMainExecutor.execute(() -> + exitSplitScreen(mMainStage.getChildCount() == 0 + ? mSideStage : mMainStage, EXIT_REASON_UNKNOWN)); + } else { + mSyncQueue.queue(evictWct); + mSyncQueue.runInSync(t -> { + setDividerVisibility(true, t); + updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */); + }); + } + } + /** * Collects all the current child tasks of a specific split and prepares transaction to evict * them to display. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java index 75a999bcb292..d89ddd2074f0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java @@ -56,7 +56,6 @@ import android.util.ArrayMap; import android.util.Slog; import android.view.ContextThemeWrapper; import android.view.SurfaceControl; -import android.view.View; import android.window.SplashScreenView; import android.window.StartingWindowInfo; import android.window.StartingWindowInfo.StartingWindowType; @@ -543,22 +542,6 @@ public class SplashscreenContentDrawer { mBrandingImageHeight); } final SplashScreenView splashScreenView = builder.build(); - if (mSuggestType != STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) { - splashScreenView.addOnAttachStateChangeListener( - new View.OnAttachStateChangeListener() { - @Override - public void onViewAttachedToWindow(View v) { - SplashScreenView.applySystemBarsContrastColor( - v.getWindowInsetsController(), - splashScreenView.getInitBackgroundColor()); - } - - @Override - public void onViewDetachedFromWindow(View v) { - } - }); - } - Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); return splashScreenView; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java index 11f23e3e941b..464ab1ae2a8c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java @@ -50,6 +50,7 @@ import android.view.Choreographer; import android.view.Display; import android.view.SurfaceControlViewHost; import android.view.View; +import android.view.WindowInsetsController; import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.widget.FrameLayout; @@ -63,6 +64,7 @@ import android.window.TaskSnapshot; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; +import com.android.internal.util.ContrastColorUtil; import com.android.launcher3.icons.IconProvider; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TransactionPool; @@ -121,6 +123,9 @@ public class StartingSurfaceDrawer { private StartingSurface.SysuiProxy mSysuiProxy; private final StartingWindowRemovalInfo mTmpRemovalInfo = new StartingWindowRemovalInfo(); + private static final int LIGHT_BARS_MASK = + WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS + | WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; /** * The minimum duration during which the splash screen is shown when the splash screen icon is * animated. @@ -361,9 +366,27 @@ public class StartingSurfaceDrawer { // the window before first round relayoutWindow, which will happen after insets // animation. mChoreographer.postCallback(CALLBACK_INSETS_ANIMATION, setViewSynchronized, null); - // Block until we get the background color. final StartingWindowRecord record = mStartingWindowRecords.get(taskId); + record.parseAppSystemBarColor(context); + // Block until we get the background color. final SplashScreenView contentView = viewSupplier.get(); + if (suggestType != STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) { + contentView.addOnAttachStateChangeListener( + new View.OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(View v) { + final int lightBarAppearance = ContrastColorUtil.isColorLight( + contentView.getInitBackgroundColor()) + ? LIGHT_BARS_MASK : 0; + contentView.getWindowInsetsController().setSystemBarsAppearance( + lightBarAppearance, LIGHT_BARS_MASK); + } + + @Override + public void onViewDetachedFromWindow(View v) { + } + }); + } record.mBGColor = contentView.getInitBackgroundColor(); } else { // release the icon view host @@ -613,6 +636,7 @@ public class StartingSurfaceDrawer { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW, "Removing splash screen window for task: %d", taskId); if (record.mContentView != null) { + record.clearSystemBarColor(); if (immediately || record.mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) { removeWindowInner(record.mDecorView, false); @@ -670,6 +694,8 @@ public class StartingSurfaceDrawer { private @StartingWindowType int mSuggestType; private int mBGColor; private final long mCreateTime; + private int mSystemBarAppearance; + private boolean mDrawsSystemBarBackgrounds; StartingWindowRecord(IBinder appToken, View decorView, TaskSnapshotWindow taskSnapshotWindow, @StartingWindowType int suggestType) { @@ -690,5 +716,37 @@ public class StartingSurfaceDrawer { mContentView = splashScreenView; mSetSplashScreen = true; } + + private void parseAppSystemBarColor(Context context) { + final TypedArray a = context.obtainStyledAttributes(R.styleable.Window); + mDrawsSystemBarBackgrounds = a.getBoolean( + R.styleable.Window_windowDrawsSystemBarBackgrounds, false); + if (a.getBoolean(R.styleable.Window_windowLightStatusBar, false)) { + mSystemBarAppearance |= WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; + } + if (a.getBoolean(R.styleable.Window_windowLightNavigationBar, false)) { + mSystemBarAppearance |= WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS; + } + a.recycle(); + } + + // Reset the system bar color which set by splash screen, make it align to the app. + private void clearSystemBarColor() { + if (mDecorView == null) { + return; + } + if (mDecorView.getLayoutParams() instanceof WindowManager.LayoutParams) { + final WindowManager.LayoutParams lp = + (WindowManager.LayoutParams) mDecorView.getLayoutParams(); + if (mDrawsSystemBarBackgrounds) { + lp.flags |= WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + } else { + lp.flags &= ~WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + } + mDecorView.setLayoutParams(lp); + } + mDecorView.getWindowInsetsController().setSystemBarsAppearance( + mSystemBarAppearance, LIGHT_BARS_MASK); + } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java index 3ea57b0520b7..9154226b7b22 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java @@ -417,7 +417,8 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { || type == TRANSIT_TO_FRONT || type == TRANSIT_TO_BACK; final boolean isTranslucent = (change.getFlags() & FLAG_TRANSLUCENT) != 0; - if (isOpenOrCloseTransition && !isTranslucent) { + if (isOpenOrCloseTransition && !isTranslucent + && wallpaperTransit == WALLPAPER_TRANSITION_NONE) { // Use the overview background as the background for the animation final Context uiContext = ActivityThread.currentActivityThread() .getSystemUiContext(); diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt index 274d34ba3c5b..0640ac526bd0 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt @@ -26,9 +26,7 @@ import com.android.server.wm.flicker.FlickerTestParameterFactory import com.android.server.wm.flicker.LAUNCHER_COMPONENT import com.android.server.wm.flicker.annotation.Group3 import com.android.server.wm.flicker.dsl.FlickerBuilder -import com.android.server.wm.flicker.rules.WMFlickerServiceRuleForTestSpec import org.junit.FixMethodOrder -import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters @@ -57,8 +55,6 @@ import org.junit.runners.Parameterized @FixMethodOrder(MethodSorters.NAME_ASCENDING) @Group3 class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) { - @get:Rule - val flickerRule = WMFlickerServiceRuleForTestSpec(testSpec) /** * Defines the transition used to run the test diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt index 9a8c8942d2c9..8da6224d990c 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt @@ -25,9 +25,7 @@ import com.android.server.wm.flicker.FlickerTestParameter import com.android.server.wm.flicker.FlickerTestParameterFactory import com.android.server.wm.flicker.annotation.Group3 import com.android.server.wm.flicker.dsl.FlickerBuilder -import com.android.server.wm.flicker.rules.WMFlickerServiceRuleForTestSpec import org.junit.FixMethodOrder -import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters @@ -57,8 +55,6 @@ import org.junit.runners.Parameterized @FixMethodOrder(MethodSorters.NAME_ASCENDING) @Group3 class ExitPipViaIntentTest(testSpec: FlickerTestParameter) : ExitPipToAppTransition(testSpec) { - @get:Rule - val flickerRule = WMFlickerServiceRuleForTestSpec(testSpec) /** * Defines the transition used to run the test diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt index 9c095a2a039f..437ad893f1d9 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt @@ -25,9 +25,7 @@ import com.android.server.wm.flicker.FlickerTestParameter import com.android.server.wm.flicker.FlickerTestParameterFactory import com.android.server.wm.flicker.annotation.Group3 import com.android.server.wm.flicker.dsl.FlickerBuilder -import com.android.server.wm.flicker.rules.WMFlickerServiceRuleForTestSpec import org.junit.FixMethodOrder -import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters @@ -57,8 +55,6 @@ import org.junit.runners.Parameterized @FixMethodOrder(MethodSorters.NAME_ASCENDING) @Group3 class ExitPipWithDismissButtonTest(testSpec: FlickerTestParameter) : ExitPipTransition(testSpec) { - @get:Rule - val flickerRule = WMFlickerServiceRuleForTestSpec(testSpec) override val transition: FlickerBuilder.() -> Unit get() = { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizerTest.java index ff6dfdb748c4..5526d5be7594 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizerTest.java @@ -44,7 +44,7 @@ import android.window.WindowContainerTransaction; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import com.android.internal.policy.ForceShowNavigationBarSettingsObserver; +import com.android.internal.policy.KidsModeSettingsObserver; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.ShellExecutor; @@ -72,7 +72,7 @@ public class KidsModeTaskOrganizerTest { @Mock private SurfaceControl mLeash; @Mock private WindowContainerToken mToken; @Mock private WindowContainerTransaction mTransaction; - @Mock private ForceShowNavigationBarSettingsObserver mObserver; + @Mock private KidsModeSettingsObserver mObserver; @Mock private StartingWindowController mStartingWindowController; @Mock private DisplayInsetsController mDisplayInsetsController; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java index 8ef1df606b43..c685fdc1f09c 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java @@ -30,7 +30,6 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import android.app.TaskInfo; -import android.graphics.Matrix; import android.graphics.Rect; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -104,7 +103,7 @@ public class PipAnimationControllerTest extends ShellTestCase { final PipAnimationController.PipTransitionAnimator oldAnimator = mPipAnimationController .getAnimator(mTaskInfo, mLeash, baseValue, startValue, endValue1, null, TRANSITION_DIRECTION_TO_PIP, 0, ROTATION_0); - oldAnimator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new); + oldAnimator.setSurfaceControlTransactionFactory(PipDummySurfaceControlTx::new); oldAnimator.start(); final PipAnimationController.PipTransitionAnimator newAnimator = mPipAnimationController @@ -134,7 +133,7 @@ public class PipAnimationControllerTest extends ShellTestCase { @Test public void pipTransitionAnimator_rotatedEndValue() { - final DummySurfaceControlTx tx = new DummySurfaceControlTx(); + final PipDummySurfaceControlTx tx = new PipDummySurfaceControlTx(); final Rect startBounds = new Rect(200, 700, 400, 800); final Rect endBounds = new Rect(0, 0, 500, 1000); // Fullscreen to PiP. @@ -184,7 +183,7 @@ public class PipAnimationControllerTest extends ShellTestCase { final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController .getAnimator(mTaskInfo, mLeash, baseValue, startValue, endValue, null, TRANSITION_DIRECTION_TO_PIP, 0, ROTATION_0); - animator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new); + animator.setSurfaceControlTransactionFactory(PipDummySurfaceControlTx::new); animator.setPipAnimationCallback(mPipAnimationCallback); @@ -201,44 +200,4 @@ public class PipAnimationControllerTest extends ShellTestCase { verify(mPipAnimationCallback).onPipAnimationEnd(eq(mTaskInfo), any(SurfaceControl.Transaction.class), eq(animator)); } - - /** - * A dummy {@link SurfaceControl.Transaction} class. - * This is created as {@link Mock} does not support method chaining. - */ - public static class DummySurfaceControlTx extends SurfaceControl.Transaction { - @Override - public SurfaceControl.Transaction setAlpha(SurfaceControl leash, float alpha) { - return this; - } - - @Override - public SurfaceControl.Transaction setPosition(SurfaceControl leash, float x, float y) { - return this; - } - - @Override - public SurfaceControl.Transaction setWindowCrop(SurfaceControl leash, int w, int h) { - return this; - } - - @Override - public SurfaceControl.Transaction setCornerRadius(SurfaceControl leash, float radius) { - return this; - } - - @Override - public SurfaceControl.Transaction setMatrix(SurfaceControl leash, Matrix matrix, - float[] float9) { - return this; - } - - @Override - public SurfaceControl.Transaction setFrameTimelineVsync(long frameTimelineVsyncId) { - return this; - } - - @Override - public void apply() {} - } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipDummySurfaceControlTx.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipDummySurfaceControlTx.java new file mode 100644 index 000000000000..ccf8f6e03844 --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipDummySurfaceControlTx.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.pip; + +import android.graphics.Matrix; +import android.view.SurfaceControl; + +/** + * A dummy {@link SurfaceControl.Transaction} class for testing purpose and supports + * method chaining. + */ +public class PipDummySurfaceControlTx extends SurfaceControl.Transaction { + @Override + public SurfaceControl.Transaction setAlpha(SurfaceControl leash, float alpha) { + return this; + } + + @Override + public SurfaceControl.Transaction setPosition(SurfaceControl leash, float x, float y) { + return this; + } + + @Override + public SurfaceControl.Transaction setWindowCrop(SurfaceControl leash, int w, int h) { + return this; + } + + @Override + public SurfaceControl.Transaction setCornerRadius(SurfaceControl leash, float radius) { + return this; + } + + @Override + public SurfaceControl.Transaction setShadowRadius(SurfaceControl leash, float radius) { + return this; + } + + @Override + public SurfaceControl.Transaction setMatrix(SurfaceControl leash, Matrix matrix, + float[] float9) { + return this; + } + + @Override + public SurfaceControl.Transaction setFrameTimelineVsync(long frameTimelineVsyncId) { + return this; + } + + @Override + public void apply() {} +} + diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java index 14d9fb9babc4..def9ad20a632 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java @@ -242,6 +242,7 @@ public class PipTaskOrganizerTest extends ShellTestCase { mPipBoundsState.setDisplayLayout(new DisplayLayout(info, mContext.getResources(), true, true)); mSpiedPipTaskOrganizer.setOneShotAnimationType(PipAnimationController.ANIM_TYPE_ALPHA); + mSpiedPipTaskOrganizer.setSurfaceControlTransactionFactory(PipDummySurfaceControlTx::new); doNothing().when(mSpiedPipTaskOrganizer).enterPipWithAlphaAnimation(any(), anyLong()); doNothing().when(mSpiedPipTaskOrganizer).scheduleAnimateResizePip(any(), anyInt(), any()); } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/tv/TvPipKeepClearAlgorithmTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/tv/TvPipKeepClearAlgorithmTest.kt index e6ba70e1b60e..9919214642fc 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/tv/TvPipKeepClearAlgorithmTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/tv/TvPipKeepClearAlgorithmTest.kt @@ -16,6 +16,7 @@ package com.android.wm.shell.pip.tv +import android.graphics.Insets import android.graphics.Rect import android.testing.AndroidTestingRunner import android.util.Size @@ -432,6 +433,64 @@ class TvPipKeepClearAlgorithmTest { assertEquals(currentTime + algorithm.stashDuration, placement.unstashTime) } + @Test + fun test_PipInsets() { + val permInsets = Insets.of(-1, -2, -3, -4) + algorithm.setPipPermanentDecorInsets(permInsets) + testInsetsForAllPositions(permInsets) + + val tempInsets = Insets.of(-4, -3, -2, -1) + algorithm.setPipPermanentDecorInsets(Insets.NONE) + algorithm.setPipTemporaryDecorInsets(tempInsets) + testInsetsForAllPositions(tempInsets) + + algorithm.setPipPermanentDecorInsets(permInsets) + algorithm.setPipTemporaryDecorInsets(tempInsets) + testInsetsForAllPositions(Insets.add(permInsets, tempInsets)) + } + + private fun testInsetsForAllPositions(insets: Insets) { + gravity = Gravity.BOTTOM or Gravity.RIGHT + testAnchorPositionWithInsets(insets) + + gravity = Gravity.BOTTOM or Gravity.LEFT + testAnchorPositionWithInsets(insets) + + gravity = Gravity.TOP or Gravity.LEFT + testAnchorPositionWithInsets(insets) + + gravity = Gravity.TOP or Gravity.RIGHT + testAnchorPositionWithInsets(insets) + + pipSize = EXPANDED_WIDE_PIP_SIZE + + gravity = Gravity.BOTTOM + testAnchorPositionWithInsets(insets) + + gravity = Gravity.TOP + testAnchorPositionWithInsets(insets) + + pipSize = Size(pipSize.height, pipSize.width) + + gravity = Gravity.LEFT + testAnchorPositionWithInsets(insets) + + gravity = Gravity.RIGHT + testAnchorPositionWithInsets(insets) + } + + private fun testAnchorPositionWithInsets(insets: Insets) { + var pipRect = Rect(0, 0, pipSize.width, pipSize.height) + pipRect.inset(insets) + var expectedBounds = Rect() + Gravity.apply(gravity, pipRect.width(), pipRect.height(), movementBounds, expectedBounds) + val reverseInsets = Insets.subtract(Insets.NONE, insets) + expectedBounds.inset(reverseInsets) + + var placement = getActualPlacement() + assertEquals(expectedBounds, placement.bounds) + } + private fun makeSideBar(width: Int, @Gravity.GravityFlags side: Int): Rect { val sidebar = Rect(0, 0, width, SCREEN_SIZE.height) if (side == Gravity.RIGHT) { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java index 49f36a4be35f..eb9d3a11d285 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java @@ -31,6 +31,7 @@ import com.android.wm.shell.TestRunningTaskInfoBuilder; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayInsetsController; +import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.common.split.SplitLayout; @@ -72,11 +73,13 @@ public class SplitTestUtils { DisplayController displayController, DisplayImeController imeController, DisplayInsetsController insetsController, SplitLayout splitLayout, Transitions transitions, TransactionPool transactionPool, - SplitscreenEventLogger logger, Optional<RecentTasksController> recentTasks, + SplitscreenEventLogger logger, ShellExecutor mainExecutor, + Optional<RecentTasksController> recentTasks, Provider<Optional<StageTaskUnfoldController>> unfoldController) { super(context, displayId, syncQueue, taskOrganizer, mainStage, sideStage, displayController, imeController, insetsController, splitLayout, - transitions, transactionPool, logger, recentTasks, unfoldController); + transitions, transactionPool, logger, mainExecutor, recentTasks, + unfoldController); // Prepare root task for testing. mRootTask = new TestRunningTaskInfoBuilder().build(); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java index f847e6eb5e96..a55f737f2f25 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java @@ -97,6 +97,7 @@ public class SplitTransitionTests extends ShellTestCase { @Mock private SurfaceSession mSurfaceSession; @Mock private SplitscreenEventLogger mLogger; @Mock private IconProvider mIconProvider; + @Mock private ShellExecutor mMainExecutor; private SplitLayout mSplitLayout; private MainStage mMainStage; private SideStage mSideStage; @@ -126,7 +127,7 @@ public class SplitTransitionTests extends ShellTestCase { mStageCoordinator = new SplitTestUtils.TestStageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue, mTaskOrganizer, mMainStage, mSideStage, mDisplayController, mDisplayImeController, mDisplayInsetsController, mSplitLayout, mTransitions, - mTransactionPool, mLogger, Optional.empty(), Optional::empty); + mTransactionPool, mLogger, mMainExecutor, Optional.empty(), Optional::empty); mSplitScreenTransitions = mStageCoordinator.getSplitTransitions(); doAnswer((Answer<IBinder>) invocation -> mock(IBinder.class)) .when(mTransitions).startTransition(anyInt(), any(), any()); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java index c571d44d3da9..42d998f6b0ee 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java @@ -54,6 +54,7 @@ import com.android.wm.shell.TestRunningTaskInfoBuilder; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayInsetsController; +import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.common.split.SplitLayout; @@ -101,6 +102,8 @@ public class StageCoordinatorTests extends ShellTestCase { private TransactionPool mTransactionPool; @Mock private SplitscreenEventLogger mLogger; + @Mock + private ShellExecutor mMainExecutor; private final Rect mBounds1 = new Rect(10, 20, 30, 40); private final Rect mBounds2 = new Rect(5, 10, 15, 20); @@ -116,7 +119,7 @@ public class StageCoordinatorTests extends ShellTestCase { mStageCoordinator = spy(new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue, mTaskOrganizer, mMainStage, mSideStage, mDisplayController, mDisplayImeController, mDisplayInsetsController, mSplitLayout, mTransitions, mTransactionPool, mLogger, - Optional.empty(), new UnfoldControllerProvider())); + mMainExecutor, Optional.empty(), new UnfoldControllerProvider())); doNothing().when(mStageCoordinator).updateActivityOptions(any(), anyInt()); when(mSplitLayout.getBounds1()).thenReturn(mBounds1); diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index ece150a4bd45..ad9aa6cdd3d9 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -108,6 +108,7 @@ cc_defaults { shared_libs: [ "android.hardware.graphics.common-V3-ndk", "android.hardware.graphics.common@1.2", + "android.hardware.graphics.composer3-V1-ndk", "liblog", "libcutils", "libutils", @@ -249,6 +250,7 @@ cc_defaults { "apex/android_matrix.cpp", "apex/android_paint.cpp", "apex/android_region.cpp", + "apex/properties.cpp", ], header_libs: ["android_graphics_apex_headers"], diff --git a/libs/hwui/apex/include/android/graphics/properties.h b/libs/hwui/apex/include/android/graphics/properties.h new file mode 100644 index 000000000000..f24f840710f9 --- /dev/null +++ b/libs/hwui/apex/include/android/graphics/properties.h @@ -0,0 +1,32 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_GRAPHICS_PROPERTIES_H +#define ANDROID_GRAPHICS_PROPERTIES_H + +#include <cutils/compiler.h> +#include <sys/cdefs.h> + +__BEGIN_DECLS + +/** + * Returns true if libhwui is using the vulkan backend. + */ +ANDROID_API bool hwui_uses_vulkan(); + +__END_DECLS + +#endif // ANDROID_GRAPHICS_PROPERTIES_H diff --git a/libs/hwui/apex/properties.cpp b/libs/hwui/apex/properties.cpp new file mode 100644 index 000000000000..abb333be159a --- /dev/null +++ b/libs/hwui/apex/properties.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "android/graphics/properties.h" + +#include <Properties.h> + +bool hwui_uses_vulkan() { + return android::uirenderer::Properties::peekRenderPipelineType() == + android::uirenderer::RenderPipelineType::SkiaVulkan; +} diff --git a/libs/hwui/libhwui.map.txt b/libs/hwui/libhwui.map.txt index 087c006a8680..fdb237387098 100644 --- a/libs/hwui/libhwui.map.txt +++ b/libs/hwui/libhwui.map.txt @@ -39,6 +39,7 @@ LIBHWUI { # platform-only /* HWUI isn't current a module, so all of these are st ARegionIterator_next; ARegionIterator_getRect; ARegionIterator_getTotalBounds; + hwui_uses_vulkan; local: *; }; diff --git a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp index ab00dd5a487c..dc72aead4873 100644 --- a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp +++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp @@ -61,6 +61,17 @@ void GLFunctorDrawable::onDraw(SkCanvas* canvas) { return; } + // canvas may be an AlphaFilterCanvas, which is intended to draw with a + // modified alpha. We do not have a way to do this without drawing into an + // extra layer, which would have a performance cost. Draw directly into the + // underlying gpu canvas. This matches prior behavior and the behavior in + // Vulkan. + { + auto* gpuCanvas = SkAndroidFrameworkUtils::getBaseWrappedCanvas(canvas); + LOG_ALWAYS_FATAL_IF(!gpuCanvas, "GLFunctorDrawable::onDraw is using an invalid canvas!"); + canvas = gpuCanvas; + } + // flush will create a GrRenderTarget if not already present. canvas->flush(); diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp index 2293ace0bd16..28f547703dde 100644 --- a/libs/hwui/utils/Color.cpp +++ b/libs/hwui/utils/Color.cpp @@ -165,6 +165,14 @@ android_dataspace ColorSpaceToADataSpace(SkColorSpace* colorSpace, SkColorType c if (SkColorSpace::Equals(colorSpace, rec2020PQ.get())) { return HAL_DATASPACE_BT2020_PQ; } + // HLG + const auto hlgFn = GetHLGScaleTransferFunction(); + if (hlgFn.has_value()) { + auto rec2020HLG = SkColorSpace::MakeRGB(hlgFn.value(), SkNamedGamut::kRec2020); + if (SkColorSpace::Equals(colorSpace, rec2020HLG.get())) { + return static_cast<android_dataspace>(HAL_DATASPACE_BT2020_HLG); + } + } LOG_ALWAYS_FATAL("Only select non-numerical transfer functions are supported"); } @@ -247,6 +255,14 @@ sk_sp<SkColorSpace> DataSpaceToColorSpace(android_dataspace dataspace) { return nullptr; } + // HLG + if ((dataspace & HAL_DATASPACE_TRANSFER_MASK) == HAL_DATASPACE_TRANSFER_HLG) { + const auto hlgFn = GetHLGScaleTransferFunction(); + if (hlgFn.has_value()) { + return SkColorSpace::MakeRGB(hlgFn.value(), gamut); + } + } + switch (dataspace & HAL_DATASPACE_TRANSFER_MASK) { case HAL_DATASPACE_TRANSFER_LINEAR: return SkColorSpace::MakeRGB(SkNamedTransferFn::kLinear, gamut); @@ -264,7 +280,6 @@ sk_sp<SkColorSpace> DataSpaceToColorSpace(android_dataspace dataspace) { return SkColorSpace::MakeRGB(SkNamedTransferFn::kRec2020, gamut); case HAL_DATASPACE_TRANSFER_UNSPECIFIED: return nullptr; - case HAL_DATASPACE_TRANSFER_HLG: default: ALOGV("Unsupported Gamma: %d", dataspace); return nullptr; @@ -381,5 +396,14 @@ skcms_TransferFunction GetPQSkTransferFunction(float sdr_white_level) { return fn; } +// Skia skcms' default HLG maps encoded [0, 1] to linear [1, 12] in order to follow ARIB +// but LinearEffect expects a decoded [0, 1] range instead to follow Rec 2100. +std::optional<skcms_TransferFunction> GetHLGScaleTransferFunction() { + std::optional<skcms_TransferFunction> hlgFn = {}; + skcms_TransferFunction_makeScaledHLGish(&hlgFn.value(), 1.f / 12.f, 2.f, 2.f, 1.f / 0.17883277f, + 0.28466892f, 0.55991073f); + return hlgFn; +} + } // namespace uirenderer } // namespace android diff --git a/libs/hwui/utils/Color.h b/libs/hwui/utils/Color.h index 1654072fd264..00f910f45c38 100644 --- a/libs/hwui/utils/Color.h +++ b/libs/hwui/utils/Color.h @@ -23,6 +23,8 @@ #include <math.h> #include <system/graphics.h> +#include <optional> + struct ANativeWindow_Buffer; struct AHardwareBuffer_Desc; @@ -127,6 +129,7 @@ struct Lab { Lab sRGBToLab(SkColor color); SkColor LabToSRGB(const Lab& lab, SkAlpha alpha); skcms_TransferFunction GetPQSkTransferFunction(float sdr_white_level = 0.f); +std::optional<skcms_TransferFunction> GetHLGScaleTransferFunction(); } /* namespace uirenderer */ } /* namespace android */ diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java index 52838898146d..8be1bcdc9479 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -187,22 +187,14 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, */ @SuppressWarnings("unused") @UnsupportedAppUsage - private long mNativeRecorderInJavaObj; + private long mNativeAudioRecordHandle; /** * Accessed by native methods: provides access to the callback data. */ @SuppressWarnings("unused") @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - private long mNativeCallbackCookie; - - /** - * Accessed by native methods: provides access to the JNIDeviceCallback instance. - */ - @SuppressWarnings("unused") - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - private long mNativeDeviceCallback; - + private long mNativeJNIDataHandle; //--------------------------------------------------------- // Member variables @@ -492,9 +484,8 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, * value here as no error checking is or can be done. */ /*package*/ AudioRecord(long nativeRecordInJavaObj) { - mNativeRecorderInJavaObj = 0; - mNativeCallbackCookie = 0; - mNativeDeviceCallback = 0; + mNativeAudioRecordHandle = 0; + mNativeJNIDataHandle = 0; // other initialization... if (nativeRecordInJavaObj != 0) { @@ -2131,7 +2122,7 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection, * @hide */ public int getPortId() { - if (mNativeRecorderInJavaObj == 0) { + if (mNativeAudioRecordHandle == 0) { return 0; } try { diff --git a/media/java/android/media/tv/tuner/filter/Filter.java b/media/java/android/media/tv/tuner/filter/Filter.java index a3e731b0ffa1..d0973f4eb11f 100644 --- a/media/java/android/media/tv/tuner/filter/Filter.java +++ b/media/java/android/media/tv/tuner/filter/Filter.java @@ -560,6 +560,11 @@ public class Filter implements AutoCloseable { */ @Override public void close() { + synchronized (mCallbackLock) { + mCallback = null; + mExecutor = null; + } + synchronized (mLock) { if (mIsClosed) { return; @@ -568,8 +573,6 @@ public class Filter implements AutoCloseable { if (res != Tuner.RESULT_SUCCESS) { TunerUtils.throwExceptionForResult(res, "Failed to close filter."); } else { - mCallback = null; - mExecutor = null; mIsStarted = false; mIsClosed = true; } diff --git a/omapi/java/android/se/omapi/SEService.java b/omapi/java/android/se/omapi/SEService.java index f42ca364b6d9..306c09afeaeb 100644 --- a/omapi/java/android/se/omapi/SEService.java +++ b/omapi/java/android/se/omapi/SEService.java @@ -118,6 +118,16 @@ public final class SEService { }); } } + + @Override + public String getInterfaceHash() { + return ISecureElementListener.HASH; + } + + @Override + public int getInterfaceVersion() { + return ISecureElementListener.VERSION; + } } private SEListener mSEListener = new SEListener(); diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java index 62e53d62fd2a..a41399fb0d0d 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java @@ -16,17 +16,18 @@ package com.android.dynsystem; +import android.annotation.NonNull; import android.content.Context; import android.gsi.AvbPublicKey; import android.gsi.IGsiService; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; -import android.os.MemoryFile; -import android.os.ParcelFileDescriptor; +import android.os.SharedMemory; import android.os.SystemProperties; import android.os.image.DynamicSystemManager; import android.service.persistentdata.PersistentDataBlockManager; +import android.system.ErrnoException; import android.util.Log; import android.util.Pair; import android.util.Range; @@ -39,6 +40,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; +import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Enumeration; import java.util.List; @@ -154,6 +156,22 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { void onResult(int resultCode, Throwable detail); } + private static class MappedMemoryBuffer implements AutoCloseable { + public ByteBuffer mBuffer; + + MappedMemoryBuffer(@NonNull ByteBuffer buffer) { + mBuffer = buffer; + } + + @Override + public void close() { + if (mBuffer != null) { + SharedMemory.unmap(mBuffer); + mBuffer = null; + } + } + } + private final int mSharedMemorySize; private final String mUrl; private final String mDsuSlot; @@ -674,59 +692,66 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { Log.d(TAG, "Start installing: " + partitionName); - MemoryFile memoryFile = new MemoryFile("dsu_" + partitionName, mSharedMemorySize); - ParcelFileDescriptor pfd = new ParcelFileDescriptor(memoryFile.getFileDescriptor()); - - mInstallationSession.setAshmem(pfd, memoryFile.length()); - - initPartitionProgress(partitionName, partitionSize, /* readonly = */ true); - publishProgress(/* installedSize = */ 0L); - long prevInstalledSize = 0; - long installedSize = 0; - byte[] bytes = new byte[memoryFile.length()]; - ExecutorService executor = Executors.newSingleThreadExecutor(); - Future<Boolean> submitPromise = null; - - while (true) { - final int numBytesRead = sis.read(bytes, 0, bytes.length); - - if (submitPromise != null) { - // Wait until the previous submit task is complete. - while (true) { - try { - if (!submitPromise.get()) { - throw new IOException("Failed submitFromAshmem() to DynamicSystem"); + try (SharedMemory sharedMemory = + SharedMemory.create("dsu_buffer_" + partitionName, mSharedMemorySize); + MappedMemoryBuffer mappedBuffer = + new MappedMemoryBuffer(sharedMemory.mapReadWrite())) { + mInstallationSession.setAshmem(sharedMemory.getFdDup(), sharedMemory.getSize()); + + initPartitionProgress(partitionName, partitionSize, /* readonly = */ true); + publishProgress(/* installedSize = */ 0L); + + long installedSize = 0; + byte[] readBuffer = new byte[sharedMemory.getSize()]; + ByteBuffer buffer = mappedBuffer.mBuffer; + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future<Boolean> submitPromise = null; + + while (true) { + final int numBytesRead = sis.read(readBuffer, 0, readBuffer.length); + + if (submitPromise != null) { + // Wait until the previous submit task is complete. + while (true) { + try { + if (!submitPromise.get()) { + throw new IOException("Failed submitFromAshmem() to DynamicSystem"); + } + break; + } catch (InterruptedException e) { + // Ignore. } - break; - } catch (InterruptedException e) { - // Ignore. } - } - // Publish the progress of the previous submit task. - if (installedSize > prevInstalledSize + MIN_PROGRESS_TO_PUBLISH) { - publishProgress(installedSize); - prevInstalledSize = installedSize; + // Publish the progress of the previous submit task. + if (installedSize > prevInstalledSize + MIN_PROGRESS_TO_PUBLISH) { + publishProgress(installedSize); + prevInstalledSize = installedSize; + } } - } - // Ensure the previous submit task (submitPromise) is complete before exiting the loop. - if (numBytesRead < 0) { - break; - } + // Ensure the previous submit task (submitPromise) is complete before exiting the + // loop. + if (numBytesRead < 0) { + break; + } - if (isCancelled()) { - return; - } + if (isCancelled()) { + return; + } - memoryFile.writeBytes(bytes, 0, 0, numBytesRead); - submitPromise = - executor.submit(() -> mInstallationSession.submitFromAshmem(numBytesRead)); + buffer.position(0); + buffer.put(readBuffer, 0, numBytesRead); + submitPromise = + executor.submit(() -> mInstallationSession.submitFromAshmem(numBytesRead)); - // Even though we update the bytes counter here, the actual progress is updated only - // after the submit task (submitPromise) is complete. - installedSize += numBytesRead; + // Even though we update the bytes counter here, the actual progress is updated only + // after the submit task (submitPromise) is complete. + installedSize += numBytesRead; + } + } catch (ErrnoException e) { + e.rethrowAsIOException(); } AvbPublicKey avbPublicKey = new AvbPublicKey(); diff --git a/packages/InputDevices/res/values-km/strings.xml b/packages/InputDevices/res/values-km/strings.xml index 4b123214a056..e06ce2c83d49 100644 --- a/packages/InputDevices/res/values-km/strings.xml +++ b/packages/InputDevices/res/values-km/strings.xml @@ -32,10 +32,10 @@ <string name="keyboard_layout_hungarian" msgid="4154963661406035109">"ហុងគ្រី"</string> <string name="keyboard_layout_icelandic" msgid="5836645650912489642">"អ៊ីស្លង់"</string> <string name="keyboard_layout_brazilian" msgid="5117896443147781939">"ប្រេស៊ីល"</string> - <string name="keyboard_layout_portuguese" msgid="2888198587329660305">"ព័រទុយហ្គាល់"</string> + <string name="keyboard_layout_portuguese" msgid="2888198587329660305">"ព័រទុយហ្កាល់"</string> <string name="keyboard_layout_slovak" msgid="2469379934672837296">"ស្លូវ៉ាគី"</string> <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"ស្លូវ៉ានី"</string> - <string name="keyboard_layout_turkish" msgid="7736163250907964898">"ទួរគី"</string> + <string name="keyboard_layout_turkish" msgid="7736163250907964898">"តួកគី"</string> <string name="keyboard_layout_turkish_f" msgid="9130320856010776018">"តួកគី F"</string> <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"អ៊ុយក្រែន"</string> <string name="keyboard_layout_arabic" msgid="5671970465174968712">"អារ៉ាប់"</string> diff --git a/packages/PackageInstaller/res/values-km/strings.xml b/packages/PackageInstaller/res/values-km/strings.xml index 525e0ef2ecf4..8306b4821e7e 100644 --- a/packages/PackageInstaller/res/values-km/strings.xml +++ b/packages/PackageInstaller/res/values-km/strings.xml @@ -46,7 +46,7 @@ <string name="out_of_space_dlg_text" msgid="8727714096031856231">"មិនអាចដំឡើង <xliff:g id="APP_NAME">%1$s</xliff:g> បានទេ។ សូមបង្កើនទំហំផ្ទុកទំនេរមួយចំនួន រួចព្យាយាមម្ដងទៀត។"</string> <string name="app_not_found_dlg_title" msgid="5107924008597470285">"រកមិនឃើញកម្មវិធីទេ"</string> <string name="app_not_found_dlg_text" msgid="5219983779377811611">"រកមិនឃើញកម្មវិធីនេះនៅក្នុងបញ្ជីកម្មវិធីដែលបានដំឡើងទេ។"</string> - <string name="user_is_not_allowed_dlg_title" msgid="6915293433252210232">"មិនអនុញ្ញាតទេ"</string> + <string name="user_is_not_allowed_dlg_title" msgid="6915293433252210232">"មិនបានអនុញ្ញាត"</string> <string name="user_is_not_allowed_dlg_text" msgid="3468447791330611681">"មិនអនុញ្ញាតឱ្យអ្នកប្រើប្រាស់បច្ចុប្បន្នធ្វើការលុបនេះទេ។"</string> <string name="generic_error_dlg_title" msgid="5863195085927067752">"បញ្ហា"</string> <string name="generic_error_dlg_text" msgid="5287861443265795232">"មិនអាចលុបកម្មវិធីបានទេ។"</string> diff --git a/packages/PackageInstaller/res/values-te/strings.xml b/packages/PackageInstaller/res/values-te/strings.xml index ab6a4ac4f899..ebc43c4b5eb5 100644 --- a/packages/PackageInstaller/res/values-te/strings.xml +++ b/packages/PackageInstaller/res/values-te/strings.xml @@ -20,7 +20,7 @@ <string name="install" msgid="711829760615509273">"ఇన్స్టాల్ చేయి"</string> <string name="update" msgid="3932142540719227615">"అప్డేట్ చేయి"</string> <string name="done" msgid="6632441120016885253">"పూర్తయింది"</string> - <string name="cancel" msgid="1018267193425558088">"రద్దు చేయి"</string> + <string name="cancel" msgid="1018267193425558088">"రద్దు చేయండి"</string> <string name="installing" msgid="4921993079741206516">"ఇన్స్టాల్ చేస్తోంది…"</string> <string name="installing_app" msgid="1165095864863849422">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>ని ఇన్స్టాల్ చేస్తోంది…"</string> <string name="install_done" msgid="5987363587661783896">"యాప్ ఇన్స్టాల్ చేయబడింది."</string> diff --git a/packages/PrintSpooler/res/values-te/strings.xml b/packages/PrintSpooler/res/values-te/strings.xml index d2254d6f956d..62cfcc4fa99e 100644 --- a/packages/PrintSpooler/res/values-te/strings.xml +++ b/packages/PrintSpooler/res/values-te/strings.xml @@ -83,7 +83,7 @@ <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>ను రద్దు చేస్తోంది"</string> <string name="failed_notification_title_template" msgid="2256217208186530973">"ప్రింటర్ ఎర్రర్ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string> <string name="blocked_notification_title_template" msgid="1175435827331588646">"ప్రింటర్ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>ను బ్లాక్ చేసింది"</string> - <string name="cancel" msgid="4373674107267141885">"రద్దు చేయి"</string> + <string name="cancel" msgid="4373674107267141885">"రద్దు చేయండి"</string> <string name="restart" msgid="2472034227037808749">"పునఃప్రారంభించు"</string> <string name="no_connection_to_printer" msgid="2159246915977282728">"ప్రింటర్కు కనెక్షన్ లేదు"</string> <string name="reason_unknown" msgid="5507940196503246139">"తెలియదు"</string> diff --git a/packages/SettingsLib/ActivityEmbedding/Android.bp b/packages/SettingsLib/ActivityEmbedding/Android.bp index 2569198f9622..332bebffb637 100644 --- a/packages/SettingsLib/ActivityEmbedding/Android.bp +++ b/packages/SettingsLib/ActivityEmbedding/Android.bp @@ -15,9 +15,15 @@ android_library { static_libs: [ "androidx.annotation_annotation", "androidx.core_core", - "windowExtLib", + "androidx.window_window", "SettingsLibUtils", ], sdk_version: "system_current", min_sdk_version: "21", + // TODO(b/228508619) Remove the optional uses after fixing upstream + optional_uses_libs: [ + "org.apache.http.legacy", + "androidx.window.extensions", + "androidx.window.sidecar", + ], } diff --git a/packages/SettingsLib/ActivityEmbedding/AndroidManifest.xml b/packages/SettingsLib/ActivityEmbedding/AndroidManifest.xml index 2e6c405f9529..5ce08b7747a4 100644 --- a/packages/SettingsLib/ActivityEmbedding/AndroidManifest.xml +++ b/packages/SettingsLib/ActivityEmbedding/AndroidManifest.xml @@ -20,4 +20,9 @@ <uses-sdk android:minSdkVersion="21" /> + <application> + <uses-library android:name="androidx.window.extensions" android:required="false" /> + <uses-library android:name="androidx.window.sidecar" android:required="false" /> + </application> + </manifest> diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/widget/CollapsingCoordinatorLayout.java b/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/widget/CollapsingCoordinatorLayout.java index eec73ff37775..72383fe59e7e 100644 --- a/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/widget/CollapsingCoordinatorLayout.java +++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/src/com/android/settingslib/collapsingtoolbar/widget/CollapsingCoordinatorLayout.java @@ -122,15 +122,66 @@ public class CollapsingCoordinatorLayout extends CoordinatorLayout { } if (activity instanceof AppCompatActivity) { - initSupportToolbar((AppCompatActivity) activity); + initSettingsStyleToolBar((SupportActionBarHost) + toolBar -> { + AppCompatActivity appCompatActivity = (AppCompatActivity) activity; + appCompatActivity.setSupportActionBar(toolBar); + return appCompatActivity.getSupportActionBar(); + }); + } else { + initSettingsStyleToolBar((ActionBarHost) + toolBar -> { + activity.setActionBar(toolBar); + return activity.getActionBar(); + }); + } + } + + /** + * Initialize some attributes of {@link ActionBar}. + * + * @param actionBarHost Host Activity that is not AppCompat. + */ + public void initSettingsStyleToolBar(ActionBarHost actionBarHost) { + if (actionBarHost == null) { + Log.w(TAG, "initSettingsStyleToolBar: actionBarHost is null"); return; } final Toolbar toolbar = findViewById(R.id.action_bar); - activity.setActionBar(toolbar); + final ActionBar actionBar = actionBarHost.setupActionBar(toolbar); + + // Enable title and home button by default + if (actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(true); + actionBar.setHomeButtonEnabled(true); + actionBar.setDisplayShowTitleEnabled(true); + } + } + + /** + * Initialize some attributes of {@link ActionBar}. + * + * @param supportActionBarHost Host Activity that is AppCompat. + */ + public void initSettingsStyleToolBar(SupportActionBarHost supportActionBarHost) { + if (supportActionBarHost == null) { + Log.w(TAG, "initSettingsStyleToolBar: supportActionBarHost is null"); + return; + } + if (mCollapsingToolbarLayout == null) { + return; + } + + mCollapsingToolbarLayout.removeAllViews(); + inflate(getContext(), R.layout.support_toolbar, mCollapsingToolbarLayout); + final androidx.appcompat.widget.Toolbar supportToolbar = + mCollapsingToolbarLayout.findViewById(R.id.support_action_bar); + + final androidx.appcompat.app.ActionBar actionBar = + supportActionBarHost.setupSupportActionBar(supportToolbar); // Enable title and home button by default - final ActionBar actionBar = activity.getActionBar(); if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeButtonEnabled(true); @@ -156,20 +207,27 @@ public class CollapsingCoordinatorLayout extends CoordinatorLayout { } } - /** - * Returns an instance of collapsing toolbar. - */ + /** Returns an instance of collapsing toolbar. */ public CollapsingToolbarLayout getCollapsingToolbarLayout() { return mCollapsingToolbarLayout; } - /** - * Return an instance of app bar. - */ + /** Return an instance of app bar. */ public AppBarLayout getAppBarLayout() { return mAppBarLayout; } + /** Returns the content frame layout. */ + public View getContentFrameLayout() { + return findViewById(R.id.content_frame); + } + + /** Returns the AppCompat Toolbar. */ + public androidx.appcompat.widget.Toolbar getSupportToolbar() { + return (androidx.appcompat.widget.Toolbar) + mCollapsingToolbarLayout.findViewById(R.id.support_action_bar); + } + private void disableCollapsingToolbarLayoutScrollingBehavior() { if (mAppBarLayout == null) { return; @@ -187,25 +245,22 @@ public class CollapsingCoordinatorLayout extends CoordinatorLayout { params.setBehavior(behavior); } - // This API is for supportActionBar of {@link AppCompatActivity} - private void initSupportToolbar(AppCompatActivity appCompatActivity) { - if (mCollapsingToolbarLayout == null) { - return; - } - - mCollapsingToolbarLayout.removeAllViews(); - inflate(getContext(), R.layout.support_toolbar, mCollapsingToolbarLayout); - final androidx.appcompat.widget.Toolbar supportToolbar = - mCollapsingToolbarLayout.findViewById(R.id.support_action_bar); - - appCompatActivity.setSupportActionBar(supportToolbar); + /** Interface to be implemented by a host Activity that is not AppCompat. */ + public interface ActionBarHost { + /** + * Sets a Toolbar as an actionBar and optionally returns an ActionBar represented by + * this toolbar if it should be used. + */ + @Nullable ActionBar setupActionBar(Toolbar toolbar); + } - // Enable title and home button by default - final androidx.appcompat.app.ActionBar actionBar = appCompatActivity.getSupportActionBar(); - if (actionBar != null) { - actionBar.setDisplayHomeAsUpEnabled(true); - actionBar.setHomeButtonEnabled(true); - actionBar.setDisplayShowTitleEnabled(true); - } + /** Interface to be implemented by a host Activity that is AppCompat. */ + public interface SupportActionBarHost { + /** + * Sets a Toolbar as an actionBar and optionally returns an ActionBar represented by + * this toolbar if it should be used. + */ + @Nullable androidx.appcompat.app.ActionBar setupSupportActionBar( + androidx.appcompat.widget.Toolbar toolbar); } } diff --git a/packages/SettingsLib/SettingsSpinner/res/layout-v31/settings_spinner_dropdown_view.xml b/packages/SettingsLib/SettingsSpinner/res/layout-v33/settings_spinner_dropdown_view.xml index cea1133f7fee..cea1133f7fee 100644 --- a/packages/SettingsLib/SettingsSpinner/res/layout-v31/settings_spinner_dropdown_view.xml +++ b/packages/SettingsLib/SettingsSpinner/res/layout-v33/settings_spinner_dropdown_view.xml diff --git a/packages/SettingsLib/SettingsSpinner/res/layout/settings_spinner_view.xml b/packages/SettingsLib/SettingsSpinner/res/layout-v33/settings_spinner_view.xml index 75de34e86bc4..1d0c9b941881 100644 --- a/packages/SettingsLib/SettingsSpinner/res/layout/settings_spinner_view.xml +++ b/packages/SettingsLib/SettingsSpinner/res/layout-v33/settings_spinner_view.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - Copyright (C) 2018 The Android Open Source Project + Copyright (C) 2022 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/packages/SettingsLib/SettingsSpinner/res/values/dimens.xml b/packages/SettingsLib/SettingsSpinner/res/values-v33/dimens.xml index d526df6bedd4..10aa84888d4e 100644 --- a/packages/SettingsLib/SettingsSpinner/res/values/dimens.xml +++ b/packages/SettingsLib/SettingsSpinner/res/values-v33/dimens.xml @@ -16,5 +16,6 @@ <resources> <dimen name="spinner_height">36dp</dimen> + <dimen name="spinner_dropdown_height">48dp</dimen> <dimen name="spinner_padding_top_or_bottom">8dp</dimen> </resources> diff --git a/packages/SettingsLib/SettingsSpinner/res/values-v31/styles.xml b/packages/SettingsLib/SettingsSpinner/res/values-v33/styles.xml index fd45a16f24ba..6e26ae180685 100644 --- a/packages/SettingsLib/SettingsSpinner/res/values-v31/styles.xml +++ b/packages/SettingsLib/SettingsSpinner/res/values-v33/styles.xml @@ -35,7 +35,7 @@ <item name="android:textColor">@color/settingslib_spinner_dropdown_color</item> <item name="android:maxLines">1</item> <item name="android:ellipsize">marquee</item> - <item name="android:minHeight">@dimen/spinner_height</item> + <item name="android:minHeight">@dimen/spinner_dropdown_height</item> <item name="android:paddingStart">16dp</item> <item name="android:paddingEnd">36dp</item> <item name="android:paddingTop">@dimen/spinner_padding_top_or_bottom</item> diff --git a/packages/SettingsLib/SettingsSpinner/res/values/styles.xml b/packages/SettingsLib/SettingsSpinner/res/values/styles.xml deleted file mode 100644 index 8ea1f9a794bc..000000000000 --- a/packages/SettingsLib/SettingsSpinner/res/values/styles.xml +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2018 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT 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> - <style name="SettingsSpinnerTitleBar"> - <item name="android:textAppearance">?android:attr/textAppearanceButton</item> - <item name="android:maxLines">1</item> - <item name="android:ellipsize">marquee</item> - <item name="android:paddingStart">16dp</item> - <item name="android:paddingEnd">36dp</item> - <item name="android:paddingTop">@dimen/spinner_padding_top_or_bottom</item> - <item name="android:paddingBottom">@dimen/spinner_padding_top_or_bottom</item> - </style> -</resources> diff --git a/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/SettingsSpinnerAdapter.java b/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/SettingsSpinnerAdapter.java index 26112074a130..7288494beb21 100644 --- a/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/SettingsSpinnerAdapter.java +++ b/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/SettingsSpinnerAdapter.java @@ -41,7 +41,7 @@ public class SettingsSpinnerAdapter<T> extends ArrayAdapter<T> { * access the current theme, resources, etc. */ public SettingsSpinnerAdapter(Context context) { - super(context, DEFAULT_RESOURCE); + super(context, getDefaultResource()); setDropDownViewResource(getDropdownResource()); mDefaultInflater = LayoutInflater.from(context); @@ -51,7 +51,7 @@ public class SettingsSpinnerAdapter<T> extends ArrayAdapter<T> { * In overridded {@link #getView(int, View, ViewGroup)}, use this method to get default view. */ public View getDefaultView(int position, View convertView, ViewGroup parent) { - return mDefaultInflater.inflate(DEFAULT_RESOURCE, parent, false /* attachToRoot */); + return mDefaultInflater.inflate(getDefaultResource(), parent, false /* attachToRoot */); } /** @@ -62,8 +62,12 @@ public class SettingsSpinnerAdapter<T> extends ArrayAdapter<T> { return mDefaultInflater.inflate(getDropdownResource(), parent, false /* attachToRoot */); } - private int getDropdownResource() { - return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) + private static int getDefaultResource() { + return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) + ? DEFAULT_RESOURCE : android.R.layout.simple_spinner_dropdown_item; + } + private static int getDropdownResource() { + return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) ? DFAULT_DROPDOWN_RESOURCE : android.R.layout.simple_spinner_dropdown_item; } } diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v31/settingslib_spinner_background.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v31/settingslib_spinner_background.xml deleted file mode 100644 index e1764afe5d91..000000000000 --- a/packages/SettingsLib/SettingsTheme/res/drawable-v31/settingslib_spinner_background.xml +++ /dev/null @@ -1,43 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2022 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - --> - -<ripple -xmlns:android="http://schemas.android.com/apk/res/android" -android:color="@color/settingslib_ripple_color"> - -<item android:id="@android:id/background"> - <layer-list android:paddingMode="stack"> - <item - android:top="8dp" - android:bottom="8dp"> - - <shape> - <corners android:radius="28dp"/> - <solid android:color="@android:color/system_accent1_100"/> - <size android:height="@dimen/settingslib_spinner_height"/> - </shape> - </item> - - <item - android:gravity="center|end" - android:width="18dp" - android:height="18dp" - android:end="12dp" - android:drawable="@drawable/settingslib_arrow_drop_down"/> - </layer-list> -</item> -</ripple> diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v31/settingslib_arrow_drop_down.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v33/settingslib_arrow_drop_down.xml index 770a69d3e8e6..770a69d3e8e6 100644 --- a/packages/SettingsLib/SettingsTheme/res/drawable-v31/settingslib_arrow_drop_down.xml +++ b/packages/SettingsLib/SettingsTheme/res/drawable-v33/settingslib_arrow_drop_down.xml diff --git a/packages/SettingsLib/SettingsTheme/res/drawable/settingslib_spinner_background.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v33/settingslib_spinner_background.xml index 746671254afd..fbda83272ddd 100644 --- a/packages/SettingsLib/SettingsTheme/res/drawable/settingslib_spinner_background.xml +++ b/packages/SettingsLib/SettingsTheme/res/drawable-v33/settingslib_spinner_background.xml @@ -16,33 +16,30 @@ --> <ripple -xmlns:android="http://schemas.android.com/apk/res/android" -android:color="@color/settingslib_ripple_color"> + xmlns:android="http://schemas.android.com/apk/res/android" + android:color="@color/settingslib_ripple_color"> <item android:id="@android:id/background"> - <layer-list android:paddingMode="stack"> + <layer-list + android:paddingMode="stack" + android:paddingStart="0dp" + android:paddingEnd="24dp"> <item android:top="8dp" android:bottom="8dp"> <shape> - <corners - android:radius="20dp"/> - <solid - android:color="?android:attr/colorPrimary"/> - <stroke - android:color="#1f000000" - android:width="1dp"/> - <size - android:height="32dp"/> + <corners android:radius="28dp"/> + <solid android:color="@android:color/system_accent1_100"/> + <size android:height="@dimen/settingslib_spinner_height"/> </shape> </item> <item android:gravity="center|end" - android:width="24dp" - android:height="24dp" - android:end="4dp" + android:width="18dp" + android:height="18dp" + android:end="12dp" android:drawable="@drawable/settingslib_arrow_drop_down"/> </layer-list> </item> diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v31/settingslib_spinner_dropdown_background.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v33/settingslib_spinner_dropdown_background.xml index 056fb828baad..50ef8fb50f19 100644 --- a/packages/SettingsLib/SettingsTheme/res/drawable-v31/settingslib_spinner_dropdown_background.xml +++ b/packages/SettingsLib/SettingsTheme/res/drawable-v33/settingslib_spinner_dropdown_background.xml @@ -20,9 +20,17 @@ android:color="@color/settingslib_ripple_color"> <item android:id="@android:id/background"> - <shape> - <corners android:radius="10dp"/> - <solid android:color="@android:color/system_accent2_100"/> - </shape> + <layer-list + android:paddingMode="stack" + android:paddingStart="0dp" + android:paddingEnd="12dp"> + + <item> + <shape> + <corners android:radius="10dp"/> + <solid android:color="@android:color/system_accent2_100"/> + </shape> + </item> + </layer-list> </item> </ripple> diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/dimens.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/dimens.xml index 29fdab13c717..11546c8ed3d9 100644 --- a/packages/SettingsLib/SettingsTheme/res/values-v31/dimens.xml +++ b/packages/SettingsLib/SettingsTheme/res/values-v31/dimens.xml @@ -25,6 +25,4 @@ <dimen name="settingslib_listPreferredItemPaddingStart">24dp</dimen> <!-- Right padding of the preference --> <dimen name="settingslib_listPreferredItemPaddingEnd">24dp</dimen> - - <dimen name="settingslib_spinner_height">36dp</dimen> </resources> diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml index b12c6d2850c4..3597ee9b08ee 100644 --- a/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml +++ b/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml @@ -45,24 +45,4 @@ <item name="android:progressDrawable">@drawable/settingslib_progress_horizontal</item> <item name="android:scaleY">0.5</item> </style> - - <style name="Spinner.SettingsLib" - parent="android:style/Widget.Material.Spinner"> - <item name="android:background">@drawable/settingslib_spinner_background</item> - <item name="android:popupBackground">@drawable/settingslib_spinner_dropdown_background</item> - <item name="android:dropDownVerticalOffset">48dp</item> - <item name="android:layout_marginTop">16dp</item> - <item name="android:layout_marginBottom">8dp</item> - </style> - - <style name="SpinnerItem.SettingsLib" - parent="@android:style/Widget.DeviceDefault.TextView.SpinnerItem"> - <item name="android:textColor">@color/settingslib_spinner_dropdown_color</item> - </style> - - <style name="SpinnerDropDownItem.SettingsLib" - parent="@android:style/Widget.Material.DropDownItem.Spinner"> - <item name="android:textColor">@color/settingslib_spinner_dropdown_color</item> - </style> - </resources> diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/themes.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/themes.xml index 4f426a3bf10c..69c122c9992e 100644 --- a/packages/SettingsLib/SettingsTheme/res/values-v31/themes.xml +++ b/packages/SettingsLib/SettingsTheme/res/values-v31/themes.xml @@ -17,7 +17,7 @@ <resources> <!-- Only using in Settings application --> - <style name="Theme.SettingsBase" parent="@android:style/Theme.DeviceDefault.Settings" > + <style name="Theme.SettingsBase_v31" parent="@android:style/Theme.DeviceDefault.Settings" > <item name="android:textAppearanceListItem">@style/TextAppearance.PreferenceTitle.SettingsLib</item> <item name="android:listPreferredItemPaddingStart">@dimen/settingslib_listPreferredItemPaddingStart</item> <item name="android:listPreferredItemPaddingLeft">@dimen/settingslib_listPreferredItemPaddingStart</item> @@ -26,11 +26,10 @@ <item name="preferenceTheme">@style/PreferenceTheme.SettingsLib</item> <item name="android:switchStyle">@style/Switch.SettingsLib</item> <item name="android:progressBarStyleHorizontal">@style/HorizontalProgressBar.SettingsLib</item> - <item name="android:spinnerStyle">@style/Spinner.SettingsLib</item> - <item name="android:spinnerItemStyle">@style/SpinnerItem.SettingsLib</item> - <item name="android:spinnerDropDownItemStyle">@style/SpinnerDropDownItem.SettingsLib</item> </style> + <style name="Theme.SettingsBase" parent="Theme.SettingsBase_v31" /> + <!-- Using in SubSettings page including injected settings page --> <style name="Theme.SubSettingsBase" parent="Theme.SettingsBase"> <!-- Suppress the built-in action bar --> diff --git a/packages/SettingsLib/SettingsTheme/res/drawable/settingslib_arrow_drop_down.xml b/packages/SettingsLib/SettingsTheme/res/values-v33/dimens.xml index 6ed215dd2dbb..bec807b395f7 100644 --- a/packages/SettingsLib/SettingsTheme/res/drawable/settingslib_arrow_drop_down.xml +++ b/packages/SettingsLib/SettingsTheme/res/values-v33/dimens.xml @@ -15,12 +15,6 @@ limitations under the License. --> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:viewportWidth="24" - android:viewportHeight="24" - android:width="24dp" - android:height="24dp"> - <path - android:pathData="M7 10l5 5 5 -5z" - android:fillColor="?android:attr/textColorPrimary"/> -</vector> +<resources> + <dimen name="settingslib_spinner_height">36dp</dimen> +</resources>
\ No newline at end of file diff --git a/packages/SettingsLib/SettingsTheme/res/values-v33/styles.xml b/packages/SettingsLib/SettingsTheme/res/values-v33/styles.xml new file mode 100644 index 000000000000..15fdfe49b0cb --- /dev/null +++ b/packages/SettingsLib/SettingsTheme/res/values-v33/styles.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2022 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> +<resources> + <style name="Spinner.SettingsLib" + parent="android:style/Widget.Material.Spinner"> + <item name="android:background">@drawable/settingslib_spinner_background</item> + <item name="android:popupBackground">@drawable/settingslib_spinner_dropdown_background + </item> + <item name="android:dropDownVerticalOffset">48dp</item> + <item name="android:layout_marginTop">16dp</item> + <item name="android:layout_marginBottom">8dp</item> + </style> + + <style name="SpinnerItem.SettingsLib" + parent="@android:style/Widget.DeviceDefault.TextView.SpinnerItem"> + <item name="android:textColor">@color/settingslib_spinner_dropdown_color</item> + <item name="android:paddingStart">16dp</item> + </style> + + <style name="SpinnerDropDownItem.SettingsLib" + parent="@android:style/Widget.Material.DropDownItem.Spinner"> + <item name="android:textColor">@color/settingslib_spinner_dropdown_color</item> + <item name="android:paddingStart">16dp</item> + </style> +</resources>
\ No newline at end of file diff --git a/packages/SettingsLib/SettingsTheme/res/values-v33/themes.xml b/packages/SettingsLib/SettingsTheme/res/values-v33/themes.xml new file mode 100644 index 000000000000..24e3c46b39ce --- /dev/null +++ b/packages/SettingsLib/SettingsTheme/res/values-v33/themes.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2022 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<resources> + <style name="Theme.SettingsBase" parent="Theme.SettingsBase_v31" > + <item name="android:spinnerStyle">@style/Spinner.SettingsLib</item> + <item name="android:spinnerItemStyle">@style/SpinnerItem.SettingsLib</item> + <item name="android:spinnerDropDownItemStyle">@style/SpinnerDropDownItem.SettingsLib</item> + </style> +</resources>
\ No newline at end of file diff --git a/packages/SettingsLib/SettingsTheme/res/values/styles.xml b/packages/SettingsLib/SettingsTheme/res/values/styles.xml index fa27bb692fe8..aaab0f041fe3 100644 --- a/packages/SettingsLib/SettingsTheme/res/values/styles.xml +++ b/packages/SettingsLib/SettingsTheme/res/values/styles.xml @@ -26,10 +26,4 @@ <style name="TextAppearance.CategoryTitle.SettingsLib" parent="@android:style/TextAppearance.DeviceDefault.Medium"> </style> - - <style name="Spinner.SettingsLib" - parent="android:style/Widget.Material.Spinner"> - <item name="android:background">@drawable/settingslib_spinner_background</item> - <item name="android:dropDownVerticalOffset">48dp</item> - </style> </resources> diff --git a/packages/SettingsLib/SettingsTheme/res/values/themes.xml b/packages/SettingsLib/SettingsTheme/res/values/themes.xml index 8dc0f3c1ff2b..2d881d1a8a7b 100644 --- a/packages/SettingsLib/SettingsTheme/res/values/themes.xml +++ b/packages/SettingsLib/SettingsTheme/res/values/themes.xml @@ -19,7 +19,6 @@ <!-- Only using in Settings application --> <style name="Theme.SettingsBase" parent="@android:style/Theme.DeviceDefault.Settings"> <item name="preferenceTheme">@style/PreferenceThemeOverlay</item> - <item name="android:spinnerStyle">@style/Spinner.SettingsLib</item> </style> <!-- Using in SubSettings page including injected settings page --> diff --git a/packages/SettingsLib/Utils/src/com/android/settingslib/utils/BuildCompatUtils.java b/packages/SettingsLib/Utils/src/com/android/settingslib/utils/BuildCompatUtils.java index 88e242340dee..ddbc907018c8 100644 --- a/packages/SettingsLib/Utils/src/com/android/settingslib/utils/BuildCompatUtils.java +++ b/packages/SettingsLib/Utils/src/com/android/settingslib/utils/BuildCompatUtils.java @@ -48,37 +48,13 @@ public final class BuildCompatUtils { } /** - * Implementation of BuildCompat.isAtLeast*() suitable for use in Settings - * - * <p>This still should try using BuildCompat.isAtLeastR() as source of truth, but also checking - * for VERSION_SDK_INT and VERSION.CODENAME in case when BuildCompat implementation returned - * false. Note that both checks should be >= and not = to make sure that when Android version - * increases (i.e., from R to S), this does not stop working. - * - * <p>Supported configurations: - * - * <ul> - * <li>For current Android release: when new API is not finalized yet (CODENAME = "Tiramisu", - * SDK_INT = 32) - * <li>For current Android release: when new API is finalized (CODENAME = "REL", SDK_INT = 33) - * <li>For next Android release (CODENAME = "U", SDK_INT = 34+) - * </ul> - * - * <p>Note that Build.VERSION_CODES.S cannot be used here until final SDK is available, because - * it is equal to Build.VERSION_CODES.CUR_DEVELOPMENT before API finalization. + * Implementation of BuildCompat.isAtLeastT() suitable for use in Settings * * @return Whether the current OS version is higher or equal to T. */ + @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.TIRAMISU) public static boolean isAtLeastT() { - if (!isAtLeastS()) { - return false; - } - - return (VERSION.CODENAME.equals("REL") && VERSION.SDK_INT >= 33) - || (VERSION.CODENAME.length() >= 1 - && VERSION.CODENAME.toUpperCase().charAt(0) >= 'T' - && VERSION.CODENAME.toUpperCase().charAt(0) <= 'Z') - || (Build.VERSION.CODENAME.equals("Tiramisu") && Build.VERSION.SDK_INT >= 32); + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU; } private BuildCompatUtils() {} diff --git a/packages/SettingsLib/res/drawable/broadcast_dialog_btn_bg.xml b/packages/SettingsLib/res/drawable/broadcast_dialog_btn_bg.xml new file mode 100644 index 000000000000..5fd7ee29d838 --- /dev/null +++ b/packages/SettingsLib/res/drawable/broadcast_dialog_btn_bg.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2022 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" + android:shape="rectangle"> + <solid android:color="?androidprv:attr/colorAccentPrimary" /> + <corners android:radius="@dimen/broadcast_dialog_btn_radius" /> +</shape> diff --git a/packages/SettingsLib/res/layout/broadcast_dialog.xml b/packages/SettingsLib/res/layout/broadcast_dialog.xml new file mode 100644 index 000000000000..ec69aa597180 --- /dev/null +++ b/packages/SettingsLib/res/layout/broadcast_dialog.xml @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2022 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <LinearLayout + android:id="@+id/dialog_bg" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/broadcast_dialog_margin" + android:orientation="vertical"> + + <ImageView + android:id="@+id/dialog_icon" + android:layout_width="@dimen/broadcast_dialog_icon_size" + android:layout_height="@dimen/broadcast_dialog_icon_size" + android:layout_marginTop="@dimen/broadcast_dialog_icon_margin_top" + android:layout_marginBottom="@dimen/broadcast_dialog_title_img_margin_top" + android:layout_gravity="center" + android:src="@drawable/settings_input_antenna"/> + + <TextView + style="@style/BroadcastDialogTitleStyle" + android:id="@+id/dialog_title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="center" + android:layout_gravity="center"/> + + <TextView + style="@style/BroadcastDialogBodyStyle" + android:id="@+id/dialog_subtitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="center" + android:layout_gravity="center"/> + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginHorizontal="@dimen/broadcast_dialog_margin" + android:layout_marginBottom="@dimen/broadcast_dialog_margin" + android:orientation="vertical"> + + <Button + android:layout_marginBottom="@dimen/broadcast_dialog_btn_margin_bottom" + android:id="@+id/positive_btn" + style="@style/BroadcastDialogButtonStyle"/> + + <Button + android:layout_marginBottom="@dimen/broadcast_dialog_btn_margin_bottom" + android:id="@+id/negative_btn" + android:text="@string/bt_le_audio_broadcast_dialog_different_output" + style="@style/BroadcastDialogButtonStyle"/> + + <Button + android:id="@+id/neutral_btn" + android:text="@android:string/cancel" + style="@style/BroadcastDialogButtonStyle"/> + </LinearLayout> + + </LinearLayout> +</FrameLayout> diff --git a/packages/SettingsLib/res/layout/qrcode_scanner_fragment.xml b/packages/SettingsLib/res/layout/qrcode_scanner_fragment.xml index e071f4c469a6..0a7fe0903348 100644 --- a/packages/SettingsLib/res/layout/qrcode_scanner_fragment.xml +++ b/packages/SettingsLib/res/layout/qrcode_scanner_fragment.xml @@ -92,6 +92,7 @@ android:layout_marginStart="?attr/sudMarginStart" android:layout_marginEnd="?attr/sudMarginEnd" android:gravity="center" + android:layout_gravity="center" android:visibility="invisible"/> </LinearLayout> diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index 53309fe3464a..378e1bb18f52 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Skandeer QR-kode"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Plaas die QR-kode hieronder in die middel om te begin luister"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR-kode is nie ’n geldige formaat nie"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Hou op om <xliff:g id="APP_NAME">%1$s</xliff:g> uit te saai?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"As jy <xliff:g id="SWITCHAPP">%1$s</xliff:g> uitsaai of die uitvoer verander, sal jou huidige uitsending stop"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Saai <xliff:g id="SWITCHAPP">%1$s</xliff:g> uit"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Verander uitvoer"</string> </resources> diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml index d24bbae4cc1a..6d833f97764a 100644 --- a/packages/SettingsLib/res/values-am/strings.xml +++ b/packages/SettingsLib/res/values-am/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR ኮድን ይቃኙ"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"ማዳመጥ ለመጀመር ከታች ያለውን QR ኮድ መሃል ላይ ያድርጉት"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR ኮድ ልክ ያልኾነ ቅርጸት ነው"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g>ን ማሰራጨት ይቁም?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"<xliff:g id="SWITCHAPP">%1$s</xliff:g>ን ካሰራጩ ወይም ውፅዓትን ከቀየሩ የአሁኑ ስርጭትዎ ይቆማል"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ያሰራጩ"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"ውፅዓትን ይቀይሩ"</string> </resources> diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml index d901b9294f0b..a3c4ac59d314 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -280,7 +280,7 @@ <string name="wifi_display_certification" msgid="1805579519992520381">"شهادة عرض شاشة لاسلكي"</string> <string name="wifi_verbose_logging" msgid="1785910450009679371">"تفعيل تسجيل Wi‑Fi Verbose"</string> <string name="wifi_scan_throttling" msgid="2985624788509913617">"تقييد البحث عن شبكات Wi-Fi"</string> - <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"التوزيع العشوائي لعناوين MAC غير الثابتة لشبكة Wi‑Fi."</string> + <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"التوزيع العشوائي لعناوين MAC غير الثابتة لشبكة Wi‑Fi"</string> <string name="mobile_data_always_on" msgid="8275958101875563572">"بيانات الجوّال نشطة دائمًا"</string> <string name="tethering_hardware_offload" msgid="4116053719006939161">"تسريع الأجهزة للتوصيل"</string> <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"عرض أجهزة البلوتوث بدون أسماء"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"إجراء مسح ضوئي لرمز الاستجابة السريعة"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"لبدء الاستماع، امسَح ضوئيًا رمز الاستجابة السريعة التالي."</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"تنسيق رمز الاستجابة السريعة غير صالح."</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"هل تريد إيقاف بث تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g>؟"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"إذا أجريت بث تطبيق <xliff:g id="SWITCHAPP">%1$s</xliff:g> أو غيَّرت جهاز الإخراج، سيتوقَف البث الحالي."</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"بث تطبيق <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"تغيير جهاز الإخراج"</string> </resources> diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml index 261ee3e50f36..b3bba95f949b 100644 --- a/packages/SettingsLib/res/values-as/strings.xml +++ b/packages/SettingsLib/res/values-as/strings.xml @@ -55,7 +55,7 @@ <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP কনফিগাৰেশ্বন বিফল হৈছে"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"নিম্নমানৰ নেটৱৰ্কৰ বাবে সংযোগ কৰা হোৱা নাই"</string> <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"ৱাই-ফাই সংযোগ বিফল হৈছে"</string> - <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"সত্য়াপন কৰাত সমস্যা হৈছে"</string> + <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"সত্যাপন কৰাত সমস্যা হৈছে"</string> <string name="wifi_cant_connect" msgid="5718417542623056783">"সংযোগ কৰিব নোৱাৰে"</string> <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\'ৰ সৈতে সংযোগ কৰিব পৰা নাই"</string> <string name="wifi_check_password_try_again" msgid="8817789642851605628">"পাছৱৰ্ড পৰীক্ষা কৰি আকৌ চেষ্টা কৰক"</string> @@ -146,12 +146,12 @@ <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"ইনপুটৰ বাবে ব্যৱহাৰ কৰক"</string> <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"শ্ৰৱণ যন্ত্ৰৰ বাবে ব্যৱহাৰ কৰক"</string> <string name="bluetooth_le_audio_profile_summary_use_for" msgid="2778318636027348572">"LE_AUDIOৰ বাবে ব্যৱহাৰ কৰক"</string> - <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"যোৰা লগাওক"</string> - <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"যোৰা লগাওক"</string> + <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"পেয়াৰ কৰক"</string> + <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"পেয়াৰ কৰক"</string> <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"বাতিল কৰক"</string> <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"যোৰা লগালে ইয়ে সংযোজিত কৰাৰ সময়ত আপোনাৰ সম্পৰ্কসমূহ আৰু কলৰ ইতিহাস চাবলৈ অনুমতি দিব।"</string> - <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>ৰ সৈতে যোৰা লগাব পৰা নগ\'ল৷"</string> - <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"এটা ভুল পিন বা পাছকীৰ কাৰণে <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ৰ সৈতে যোৰা লগাব পৰা নাই৷"</string> + <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>ৰ সৈতে পেয়াৰ কৰিব পৰা নগ’ল।"</string> + <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"এটা ভুল পিন বা পাছকীৰ কাৰণে <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ৰ সৈতে পেয়াৰ কৰিব পৰা নাই।"</string> <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>ৰ সৈতে যোগাযোগ কৰিব পৰা নগ\'ল"</string> <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>এ যোৰা লগাব বিচৰা নাই"</string> <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"কম্পিউটাৰ"</string> @@ -297,8 +297,8 @@ <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"ধোঁৱাবৰণীয়া হৈ থকা মানে এয়া ফ’ন অথবা হেডছেটটোৱে সমৰ্থন নকৰে"</string> <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"প্ৰতি ছেম্পলত ব্লুটুথ অডিঅ\' বিটসমূহ"</string> <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ব্লুটুথ অডিঅ\' ক\'ডেকৰ বাছনি\nআৰম্ভ কৰক: প্ৰতি নমুনা ইমান বিট"</string> - <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ব্লুটুথ অডিঅ\' চ্চেনেল ম\'ড"</string> - <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="2076949781460359589">"ব্লুটুথ অডিঅ\' ক\'ডেকৰ বাছনি\nআৰম্ভ কৰক: চ্চেনেল ম\'ড"</string> + <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ব্লুটুথ অডিঅ\' চেনেল ম\'ড"</string> + <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="2076949781460359589">"ব্লুটুথ অডিঅ\' ক\'ডেকৰ বাছনি\nআৰম্ভ কৰক: চেনেল ম\'ড"</string> <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3233402355917446304">"ব্লুটুথ অডিঅ’ LDAC ক’ডেক: পৰিৱেশনৰ মান"</string> <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="7274396574659784285">"ব্লুটুথ অডিঅ\' LDAC\nক\'ডেক বাছনি আৰম্ভ কৰক: প্লেবেকৰ গুণগত মান"</string> <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="2040810756832027227">"ষ্ট্ৰীম কৰি থকা হৈছে: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string> @@ -401,7 +401,7 @@ <string name="show_all_anrs" msgid="9160563836616468726">"নেপথ্য এএনআৰবোৰ দেখুৱাওক"</string> <string name="show_all_anrs_summary" msgid="8562788834431971392">"নেপথ্য এপসমূহৰ বাবে এপে সঁহাৰি দিয়া নাই ডায়ল\'গ প্ৰদৰ্শন কৰক"</string> <string name="show_notification_channel_warnings" msgid="3448282400127597331">"জাননী চ্চেনেলৰ সকীয়নিসমূহ দেখুৱাওক"</string> - <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"কোনো এপে বৈধ চ্চেনেল নোহোৱাকৈ কোনো জাননী প\'ষ্ট কৰিলে স্ক্ৰীনত সকীয়নি প্ৰদৰ্শন হয়"</string> + <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"কোনো এপে বৈধ চেনেল নোহোৱাকৈ কোনো জাননী প\'ষ্ট কৰিলে স্ক্ৰীনত সকীয়নি প্ৰদৰ্শন হয়"</string> <string name="force_allow_on_external" msgid="9187902444231637880">"বাহ্যিক সঞ্চয়াগাৰত এপক বলেৰে অনুমতি দিয়ক"</string> <string name="force_allow_on_external_summary" msgid="8525425782530728238">"মেনিফেষ্টৰ মান যিয়েই নহওক, বাহ্যিক ষ্ট’ৰেজত লিখিবলৈ যিকোনো এপক উপযুক্ত কৰি তোলে"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"বলেৰে কাৰ্যকলাপসমূহৰ আকাৰ সলনি কৰিব পৰা কৰক"</string> @@ -569,7 +569,7 @@ <string name="user_add_user_item_title" msgid="2394272381086965029">"ব্যৱহাৰকাৰী"</string> <string name="user_add_profile_item_title" msgid="3111051717414643029">"সীমিত প্ৰ\'ফাইল"</string> <string name="user_add_user_title" msgid="5457079143694924885">"নতুন ব্যৱহাৰকাৰী যোগ কৰিবনে?"</string> - <string name="user_add_user_message_long" msgid="1527434966294733380">"আপুনি অতিৰিক্ত ব্য়ৱহাৰকাৰীক যোগ কৰি এই ডিভাইচটো অন্য় ব্য়ক্তিৰ সৈতে শ্বেয়াৰ কৰিব পাৰে। প্ৰতিজন ব্য়ৱহাৰকাৰীৰ বাবে নিজাকৈ ঠাই আছে যাক তেওঁলোকে এপ্, ৱালপেপাৰ আৰু অন্য়ান্য় বস্তুৰ বাবে নিজৰ উপযোগিতা অনুযায়ী ব্য়ৱহাৰ কৰিব পাৰে। ব্য়ৱহাৰকাৰীসকলে সকলোকে প্ৰভাৱান্বিত কৰা ৱাই-ফাইৰ নিচিনা ডিভাইচৰ ছেটিং সাল-সলনি কৰিবও পাৰে।\n\nআপুনি যেতিয়া কোনো নতুন ব্য়ৱহাৰকাৰীক যোগ কৰে সেই ব্য়ক্তিজনে নিজেই নিজৰ বাবে ঠাই ছেট আপ কৰিব লাগিব।\n\nসকলো ব্য়ৱহাৰকাৰীয়ে অন্য় ব্য়ৱহাৰকাৰীৰ বাবে এপ্সমূহ আপডে’ট কৰিব পাৰে। সাধ্য় সুবিধাসমূহৰ ছেটিং আৰু সেৱাসমূহ নতুন ব্য়ৱহাৰকাৰীলৈ স্থানান্তৰ নহ\'বও পাৰে।"</string> + <string name="user_add_user_message_long" msgid="1527434966294733380">"আপুনি অতিৰিক্ত ব্যৱহাৰকাৰীক যোগ কৰি এই ডিভাইচটো অন্য় ব্য়ক্তিৰ সৈতে শ্বেয়াৰ কৰিব পাৰে। প্ৰতিজন ব্যৱহাৰকাৰীৰ বাবে নিজাকৈ ঠাই আছে যাক তেওঁলোকে এপ্, ৱালপেপাৰ আৰু অন্য়ান্য় বস্তুৰ বাবে নিজৰ উপযোগিতা অনুযায়ী ব্যৱহাৰ কৰিব পাৰে। ব্যৱহাৰকাৰীসকলে সকলোকে প্ৰভাৱান্বিত কৰা ৱাই-ফাইৰ নিচিনা ডিভাইচৰ ছেটিং সাল-সলনি কৰিবও পাৰে।\n\nআপুনি যেতিয়া কোনো নতুন ব্যৱহাৰকাৰীক যোগ কৰে সেই ব্য়ক্তিজনে নিজেই নিজৰ বাবে ঠাই ছেট আপ কৰিব লাগিব।\n\nসকলো ব্যৱহাৰকাৰীয়ে অন্য় ব্যৱহাৰকাৰীৰ বাবে এপ্সমূহ আপডে’ট কৰিব পাৰে। সাধ্য় সুবিধাসমূহৰ ছেটিং আৰু সেৱাসমূহ নতুন ব্যৱহাৰকাৰীলৈ স্থানান্তৰ নহ\'বও পাৰে।"</string> <string name="user_add_user_message_short" msgid="3295959985795716166">"আপুনি যেতিয়া এজন নতুন ব্যৱহাৰকাৰী যোগ কৰে, তেওঁ নিজৰ ঠাই ছেট আপ কৰা প্ৰয়োজন।\n\nযিকোনো ব্যৱহাৰকাৰীয়ে সকলো ব্যৱহাৰকাৰীৰ বাবে এপ্ আপডে\'ট কৰিব পাৰে।"</string> <string name="user_setup_dialog_title" msgid="8037342066381939995">"ব্যৱহাৰকাৰী এতিয়া ছেট আপ কৰিবনে?"</string> <string name="user_setup_dialog_message" msgid="269931619868102841">"ডিভাইচটো লৈ নিজৰ ঠাই ছেটআপ কৰিবলৈ নতুন ব্যৱহাৰকাৰী উপলব্ধ থকাটো নিশ্চিত কৰক"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"কিউআৰ ক’ডটো স্কেন কৰক"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"শুনিবলৈ আৰম্ভ কৰিবলৈ, তলৰ মাজৰ অংশত কিউআৰ ক’ডটো ৰাখক"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"কিউআৰ ক’ডটো মান্য ফৰ্মেটৰ নহয়"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ সম্প্ৰচাৰ কৰা বন্ধ কৰিবনে?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"যদি আপুনি <xliff:g id="SWITCHAPP">%1$s</xliff:g>ৰ সম্প্ৰচাৰ কৰে অথবা আউটপুট সলনি কৰে, তেন্তে, আপোনাৰ বৰ্তমানৰ সম্প্ৰচাৰ বন্ধ হৈ যাব"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> সম্প্ৰচাৰ কৰক"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"আউটপুট সলনি কৰক"</string> </resources> diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml index fa8c5155be30..ca78c68c83df 100644 --- a/packages/SettingsLib/res/values-az/strings.xml +++ b/packages/SettingsLib/res/values-az/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR kodu skanlayın"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Dinləməyə başlamaq üçün aşağıda QR kodu mərkəzə yerləşdirin"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR kodu doğru formatda deyil"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqinin yayımlanması dayandırılsın?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> tətbiqini yayımlasanız və ya nəticəni dəyişsəniz, cari yayımınız dayandırılacaq"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> tətbiqini yayımlayın"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Nəticəni dəyişdirin"</string> </resources> diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml index fb7e21d78caa..0da57e4e7746 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Skenirajte QR kôd"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Da biste počeli da slušate, centrirajte QR kôd ispod"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR kôd nije u važećem formatu"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Želite da zaustavite emitovanje aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Ako emitujete aplikaciju <xliff:g id="SWITCHAPP">%1$s</xliff:g> ili promenite izlaz, aktuelno emitovanje će se zaustaviti"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Emitujte aplikaciju <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Promenite izlaz"</string> </resources> diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml index da9caf604a7d..7c58ee7de9dc 100644 --- a/packages/SettingsLib/res/values-be/strings.xml +++ b/packages/SettingsLib/res/values-be/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Сканіраваць QR-код"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Каб пачаць праслухванне, памясціце ў цэнтр QR-код, які знаходзіцца ўнізе"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR-код мае несапраўдны фармат"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Спыніць трансляцыю праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Пры пераключэнні на праграму \"<xliff:g id="SWITCHAPP">%1$s</xliff:g>\" ці змяненні вываду бягучая трансляцыя спыняецца"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Трансляцыя праграмы \"<xliff:g id="SWITCHAPP">%1$s</xliff:g>\""</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Змяненне вываду"</string> </resources> diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml index 82bff5ff41bf..49e66c0f74e6 100644 --- a/packages/SettingsLib/res/values-bg/arrays.xml +++ b/packages/SettingsLib/res/values-bg/arrays.xml @@ -247,7 +247,7 @@ <item msgid="5023908510820531131">"След <xliff:g id="AS_TYPED_COMMAND">adb shell dumpsys gfxinfo</xliff:g>"</item> </string-array> <string-array name="debug_hw_overdraw_entries"> - <item msgid="1968128556747588800">"Изключено"</item> + <item msgid="1968128556747588800">"Изкл."</item> <item msgid="3033215374382962216">"Области за преизчертаване: Показв."</item> <item msgid="3474333938380896988">"Показване на областите за деутеранопия"</item> </string-array> diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml index c5ac71cea8ca..f35ed0e8d0a4 100644 --- a/packages/SettingsLib/res/values-bg/strings.xml +++ b/packages/SettingsLib/res/values-bg/strings.xml @@ -225,7 +225,7 @@ <string name="choose_profile" msgid="343803890897657450">"Избор на потребителски профил"</string> <string name="category_personal" msgid="6236798763159385225">"Лични"</string> <string name="category_work" msgid="4014193632325996115">"Служебни"</string> - <string name="development_settings_title" msgid="140296922921597393">"Опции на програмиста"</string> + <string name="development_settings_title" msgid="140296922921597393">"Опции за програмисти"</string> <string name="development_settings_enable" msgid="4285094651288242183">"Активиране на опциите за програмисти"</string> <string name="development_settings_summary" msgid="8718917813868735095">"Задаване на опции за програмиране на приложения"</string> <string name="development_settings_not_available" msgid="355070198089140951">"Опциите за програмисти не са налице за този потребител"</string> @@ -364,7 +364,7 @@ <string name="pointer_location_summary" msgid="957120116989798464">"Насл. на екран показва текущи данни при докосване"</string> <string name="show_touches" msgid="8437666942161289025">"Показване на докосванията"</string> <string name="show_touches_summary" msgid="3692861665994502193">"Показване на визуална обр. връзка за докосванията"</string> - <string name="show_screen_updates" msgid="2078782895825535494">"Актуал. на повърхн: Показв."</string> + <string name="show_screen_updates" msgid="2078782895825535494">"Актуализации на повърхн."</string> <string name="show_screen_updates_summary" msgid="2126932969682087406">"Примигв. на целите повърхности на прозорците при актуализирането им"</string> <string name="show_hw_screen_updates" msgid="2021286231267747506">"Актуализации на изгледите"</string> <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"Примигв. на изгледите в прозорците при начертаване"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Сканиране на QR код"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"За да започнете да слушате, центрирайте QR кода по-долу"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"Невалиден формат на QR кода"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Да се спре ли предаването на <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Ако предавате <xliff:g id="SWITCHAPP">%1$s</xliff:g> или промените изхода, текущото ви предаване ще бъде прекратено"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Предаване на <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Промяна на изхода"</string> </resources> diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml index 11e9f1df5778..7d4208120491 100644 --- a/packages/SettingsLib/res/values-bn/strings.xml +++ b/packages/SettingsLib/res/values-bn/strings.xml @@ -273,7 +273,7 @@ <string name="oem_unlock_enable_summary" msgid="5857388174390953829">"বুট-লোডার আনলক করার অনুমতি দিন"</string> <string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"OEM আনলক করার অনুমতি দিতে চান?"</string> <string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"সতর্কতা: এই ডিভাইসে সেটিংটি চালু থাকা অবস্থায় ডিভাইস সুরক্ষা বৈশিষ্ট্যগুলি কাজ করবে না৷"</string> - <string name="mock_location_app" msgid="6269380172542248304">"অনুরূপ লোকেশন অ্যাপ্লিকেশান বেছে নিন"</string> + <string name="mock_location_app" msgid="6269380172542248304">"অনুরূপ লোকেশন অ্যাপ বেছে নিন"</string> <string name="mock_location_app_not_set" msgid="6972032787262831155">"কোনো অনুরূপ লোকেশন অ্যাপ্লিকেশান সেট করা নেই"</string> <string name="mock_location_app_set" msgid="4706722469342913843">"অনুরূপ লোকেশন অ্যাপ্লিকেশান: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="debug_networking_category" msgid="6829757985772659599">"নেটওয়ার্কিং"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR কোড স্ক্যান করুন"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"শোনা শুরু করতে, নিচের QR কোডটি মাঝখানে রাখুন"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR কোডের ফর্ম্যাট সঠিক নয়"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> সম্প্রচার বন্ধ করবেন?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"আপনি <xliff:g id="SWITCHAPP">%1$s</xliff:g> সম্প্রচার করলে বা আউটপুট পরিবর্তন করলে, আপনার বর্তমান সম্প্রচার বন্ধ হয়ে যাবে"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> সম্প্রচার করুন"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"আউটপুট পরিবর্তন করুন"</string> </resources> diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml index 7499bbce1857..93941218546a 100644 --- a/packages/SettingsLib/res/values-bs/strings.xml +++ b/packages/SettingsLib/res/values-bs/strings.xml @@ -264,7 +264,7 @@ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Povežite se na WiFi mrežu"</string> <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, otklanjanje grešaka, programer"</string> <string name="bugreport_in_power" msgid="8664089072534638709">"Prečica za izvještaj o greškama"</string> - <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Prikaz dugmeta za prijavu grešaka u meniju napajanja"</string> + <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Vidite dugme za prijavu grešaka u meniju napajanja"</string> <string name="keep_screen_on" msgid="1187161672348797558">"Ne zaključavaj ekran"</string> <string name="keep_screen_on_summary" msgid="1510731514101925829">"Ekran neće prelaziti u stanje mirovanja tokom punjenja"</string> <string name="bt_hci_snoop_log" msgid="7291287955649081448">"Omogući Bluetooth HCI snoop zapis"</string> @@ -299,8 +299,8 @@ <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"Aktivirajte Bluetooth Audio Codec\nOdabir: Bitovi po uzorku"</string> <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"Način Bluetooth audio kanala"</string> <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="2076949781460359589">"Aktivirajte Bluetooth Audio Codec\nOdabir: Način rada po kanalima"</string> - <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3233402355917446304">"Bluetooth Audio LDAC kodek: Kvalitet reprodukcije"</string> - <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="7274396574659784285">"Aktivirajte Bluetooth Audio \nOdabir kodeka: Kvalitet reprodukcije"</string> + <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3233402355917446304">"Bluetooth Audio LDAC kodek: kvalitet reprodukcije"</string> + <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="7274396574659784285">"Aktivirajte Bluetooth Audio \nOdabir kodeka: kvalitet reprodukcije"</string> <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="2040810756832027227">"Prijenos: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string> <string name="select_private_dns_configuration_title" msgid="7887550926056143018">"Privatni DNS"</string> <string name="select_private_dns_configuration_dialog_title" msgid="3731422918335951912">"Odaberite način rada privatnog DNS-a"</string> @@ -336,7 +336,7 @@ <string name="dev_settings_warning_title" msgid="8251234890169074553">"Dopustiti postavke za razvoj?"</string> <string name="dev_settings_warning_message" msgid="37741686486073668">"Ove postavke su namijenjene samo za svrhe razvoja. Mogu izazvati pogrešno ponašanje uređaja i aplikacija na njemu."</string> <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"Potvrdi aplikacije putem USB-a"</string> - <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Provjerite da li se u aplikacijama instaliranim putem ADB-a/ADT-a javlja zlonamjerno ponašanje"</string> + <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Provjerite javlja li se zlonamjerno ponašanje u aplikacijama instaliranim putem ADB-a/ADT-a"</string> <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Prikazat će se Bluetooth uređaji bez naziva (samo MAC adrese)"</string> <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Onemogućava funkciju apsolutne jačine zvuka za Bluetooth u slučaju problema s jačinom zvuka na udaljenim uređajima, kao što je neprihvatljivo glasan zvuk ili nedostatak kontrole."</string> <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Omogućava grupisanje funkcije Bluetooth Gabeldorsche."</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Skenirajte QR kôd"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Da pokrenete slušanje, centrirajte QR kôd ispod"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"Format QR koda nije važeći"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Zaustaviti emitiranje aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Ako emitirate aplikaciju <xliff:g id="SWITCHAPP">%1$s</xliff:g> ili promijenite izlaz, trenutno emitiranje će se zaustaviti"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Emitiraj aplikaciju <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Promijeni izlaz"</string> </resources> diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index 5620cce8884d..91dcbc91ab88 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -312,7 +312,7 @@ <string name="wifi_display_certification_summary" msgid="8111151348106907513">"Mostra les opcions per a la certificació de pantalla sense fil"</string> <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Augmenta el nivell de registre de la connexió Wi‑Fi i es mostra per SSID RSSI al selector de Wi‑Fi"</string> <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Exhaureix menys la bateria i millora el rendiment de la xarxa"</string> - <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Quan aquest mode està activat, és possible que l’adreça MAC d\'aquest dispositiu canviï cada vegada que es connecti a una xarxa amb l\'aleatorització d\'adreces MAC activada."</string> + <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Quan aquest mode està activat, és possible que l’adreça MAC d\'aquest dispositiu canviï cada vegada que es connecti a una xarxa amb l\'aleatorització d\'adreces MAC activada"</string> <string name="wifi_metered_label" msgid="8737187690304098638">"D\'ús mesurat"</string> <string name="wifi_unmetered_label" msgid="6174142840934095093">"D\'ús no mesurat"</string> <string name="select_logd_size_title" msgid="1604578195914595173">"Mides de la mem. intermèdia del registrador"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Escaneja un codi QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Per començar a escoltar, centra el codi QR més avall"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"El codi QR no té un format vàlid"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Vols deixar d\'emetre <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Si emets <xliff:g id="SWITCHAPP">%1$s</xliff:g> o canvies la sortida, l\'emissió actual s\'aturarà"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Emet <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Canvia la sortida"</string> </resources> diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml index 8d4aacd5e83d..7729815c5ff4 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -173,9 +173,9 @@ <string name="data_usage_uninstalled_apps" msgid="1933665711856171491">"Odebrané aplikace"</string> <string name="data_usage_uninstalled_apps_users" msgid="5533981546921913295">"Odebrané aplikace a odebraní uživatelé"</string> <string name="data_usage_ota" msgid="7984667793701597001">"Aktualizace systému"</string> - <string name="tether_settings_title_usb" msgid="3728686573430917722">"Připojení přes USB"</string> + <string name="tether_settings_title_usb" msgid="3728686573430917722">"Tethering přes USB"</string> <string name="tether_settings_title_wifi" msgid="4803402057533895526">"Přenosný hotspot"</string> - <string name="tether_settings_title_bluetooth" msgid="916519902721399656">"Připojení přes Bluetooth"</string> + <string name="tether_settings_title_bluetooth" msgid="916519902721399656">"Tethering přes Bluetooth"</string> <string name="tether_settings_title_usb_bluetooth" msgid="1727111807207577322">"Sdílené připojení"</string> <string name="tether_settings_title_all" msgid="8910259483383010470">"Sdílené připojení a přenosný hotspot"</string> <string name="managed_user_title" msgid="449081789742645723">"Všechny pracovní aplikace"</string> @@ -310,7 +310,7 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="6564868953748514595">"Zadejte hostitele poskytovatele DNS"</string> <string name="private_dns_mode_provider_failure" msgid="8356259467861515108">"Nelze se připojit"</string> <string name="wifi_display_certification_summary" msgid="8111151348106907513">"Zobrazit možnosti certifikace bezdrátového displeje"</string> - <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Zvýšit úroveň protokolování Wi‑Fi zobrazenou v SSID a RSSI při výběru sítě Wi‑Fi"</string> + <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Zvýšit úroveň protokolování Wi‑Fi, při výběru Wi‑Fi zobrazovat RSSI pro každý SSID"</string> <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Snižuje vyčerpávání baterie a vylepšuje výkon sítě"</string> <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Když je tento režim aktivován, adresa MAC tohoto zařízení se může změnit pokaždé, když se zařízení připojí k síti s aktivovanou randomizací adres MAC."</string> <string name="wifi_metered_label" msgid="8737187690304098638">"Měřená"</string> @@ -336,7 +336,7 @@ <string name="dev_settings_warning_title" msgid="8251234890169074553">"Povolit nastavení pro vývojáře?"</string> <string name="dev_settings_warning_message" msgid="37741686486073668">"Tato nastavení jsou určena pouze pro vývojáře. Mohou způsobit rozbití nebo nesprávné fungování zařízení a nainstalovaných aplikací."</string> <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"Ověřovat aplikace z USB"</string> - <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Kontrolovat škodlivost aplikací nainstalovaných pomocí nástroje ADB/ADT"</string> + <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Kontrolovat škodlivost aplikací nainstalovaných pomocí nástroje ADB nebo ADT"</string> <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Zařízení Bluetooth se budou zobrazovat bez názvů (pouze adresy MAC)"</string> <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Zakáže funkci absolutní hlasitosti Bluetooth. Zabrání tak problémům s hlasitostí vzdálených zařízení (jako je příliš vysoká hlasitost nebo nemožnost ovládání)."</string> <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Zapne sadu funkcí Bluetooth Gabeldorche."</string> @@ -351,7 +351,7 @@ <string name="debug_app_set" msgid="6599535090477753651">"Aplikace pro ladění: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="select_application" msgid="2543228890535466325">"Výběr aplikace"</string> <string name="no_application" msgid="9038334538870247690">"Nic"</string> - <string name="wait_for_debugger" msgid="7461199843335409809">"Počkat na ladicí program"</string> + <string name="wait_for_debugger" msgid="7461199843335409809">"Čekat na ladicí program"</string> <string name="wait_for_debugger_summary" msgid="6846330006113363286">"Aplikace čeká na připojení ladicího programu"</string> <string name="debug_input_category" msgid="7349460906970849771">"Vstup"</string> <string name="debug_drawing_category" msgid="5066171112313666619">"Vykreslování"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Skenování QR kódu"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Pokud chcete začít poslouchat, zaměřte QR kód níže"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR kód není platný formát"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Zastavit vysílání v aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Pokud budete vysílat v aplikaci <xliff:g id="SWITCHAPP">%1$s</xliff:g> nebo změníte výstup, aktuální vysílání se zastaví"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Vysílat v aplikaci <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Změna výstupu"</string> </resources> diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index c982aa76e38d..6f4846ee8755 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Scan QR-kode"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Centrer QR-koden nedenfor for at gå i gang med at lytte"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR-koden har ikke et gyldigt format"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Stop udsendelsen <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Hvis du udsender <xliff:g id="SWITCHAPP">%1$s</xliff:g> eller skifter output, stopper din aktuelle udsendelse"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Udsend <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Skift output"</string> </resources> diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml index 68d025602b76..7d66c837d53b 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR-Code scannen"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Scanne zum Anhören den QR-Code unten"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"Das Format des QR-Codes ist nicht gültig"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> nicht mehr streamen?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Wenn du <xliff:g id="SWITCHAPP">%1$s</xliff:g> streamst oder die Ausgabe änderst, wird dein aktueller Stream beendet"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> streamen"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Ausgabe ändern"</string> </resources> diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml index 44fd24fd0287..0f04846856bc 100644 --- a/packages/SettingsLib/res/values-el/strings.xml +++ b/packages/SettingsLib/res/values-el/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Σάρωση κωδικού QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Για έναρξη της ακρόασης, κεντράρετε τον παρακάτω κωδικό QR"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"Ο κωδικός QR δεν έχει έγκυρη μορφή"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Διακοπή μετάδοσης με την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>;"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Εάν κάνετε μετάδοση με την εφαρμογή <xliff:g id="SWITCHAPP">%1$s</xliff:g> ή αλλάξετε την έξοδο, η τρέχουσα μετάδοση θα σταματήσει"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Μετάδοση με την εφαρμογή <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Αλλαγή εξόδου"</string> </resources> diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml index e9a8da988001..74e2dbbd05c9 100644 --- a/packages/SettingsLib/res/values-en-rAU/strings.xml +++ b/packages/SettingsLib/res/values-en-rAU/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Scan QR code"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"To start listening, centre the QR code below"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR code isn\'t a valid format"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Stop broadcasting <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"If you broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g> or change the output, your current broadcast will stop"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Change output"</string> </resources> diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml index 788968f438c1..eacaad02883f 100644 --- a/packages/SettingsLib/res/values-en-rCA/strings.xml +++ b/packages/SettingsLib/res/values-en-rCA/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Scan QR code"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"To start listening, centre the QR code below"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR code isn\'t a valid format"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Stop broadcasting <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"If you broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g> or change the output, your current broadcast will stop"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Change output"</string> </resources> diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml index e9a8da988001..74e2dbbd05c9 100644 --- a/packages/SettingsLib/res/values-en-rGB/strings.xml +++ b/packages/SettingsLib/res/values-en-rGB/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Scan QR code"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"To start listening, centre the QR code below"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR code isn\'t a valid format"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Stop broadcasting <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"If you broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g> or change the output, your current broadcast will stop"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Change output"</string> </resources> diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml index e9a8da988001..74e2dbbd05c9 100644 --- a/packages/SettingsLib/res/values-en-rIN/strings.xml +++ b/packages/SettingsLib/res/values-en-rIN/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Scan QR code"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"To start listening, centre the QR code below"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR code isn\'t a valid format"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Stop broadcasting <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"If you broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g> or change the output, your current broadcast will stop"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Change output"</string> </resources> diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml index 9ca21bb42821..70227dce71e4 100644 --- a/packages/SettingsLib/res/values-en-rXC/strings.xml +++ b/packages/SettingsLib/res/values-en-rXC/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Scan QR code"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"To start listening, center the QR code below"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR code isn\'t a valid format"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Stop broadcasting <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"If you broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g> or change the output, your current broadcast will stop"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Broadcast <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Change output"</string> </resources> diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index 20baf883cd90..d96e7f07a161 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Escanear código QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Para comenzar a escuchar, centra el código QR que aparece a continuación"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"El código QR no tiene un formato válido"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"¿Quieres dejar de transmitir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Si transmites <xliff:g id="SWITCHAPP">%1$s</xliff:g> o cambias la salida, tu transmisión actual se detendrá"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Transmitir <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Cambia la salida"</string> </resources> diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index 6ec3f8e7ef30..f9c6121c2eae 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -286,10 +286,10 @@ <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Mostrar dispositivos Bluetooth sin nombre"</string> <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Inhabilitar volumen absoluto"</string> <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Habilitar Gabeldorsche"</string> - <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versión AVRCP de Bluetooth"</string> - <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Selecciona la versión AVRCP de Bluetooth"</string> - <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Versión de MAP de Bluetooth"</string> - <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Seleccionar versión de MAP de Bluetooth"</string> + <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Versión de Bluetooth AVRCP"</string> + <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Selecciona la versión de Bluetooth AVRCP"</string> + <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Versión de Bluetooth MAP"</string> + <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Selecciona la versión de Bluetooth MAP"</string> <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Códec de audio de Bluetooth"</string> <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Activar el códec de audio por Bluetooth\nSelección"</string> <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Frecuencia de muestreo de audio de Bluetooth"</string> @@ -311,11 +311,11 @@ <string name="private_dns_mode_provider_failure" msgid="8356259467861515108">"No se ha podido establecer la conexión"</string> <string name="wifi_display_certification_summary" msgid="8111151348106907513">"Muestra opciones para la certificación de la pantalla inalámbrica"</string> <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Aumenta el nivel de registro de la conexión Wi-Fi y se muestra por SSID RSSI en el selector Wi-Fi"</string> - <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Reduce el consumo de batería y mejora el rendimiento de las redes"</string> + <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Reduce el consumo de batería y mejora el rendimiento de la red"</string> <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Si este modo está habilitado, es posible que la dirección MAC del dispositivo cambie cada vez que se conecte a una red que tenga habilitada la aleatorización de MAC."</string> <string name="wifi_metered_label" msgid="8737187690304098638">"Medida"</string> <string name="wifi_unmetered_label" msgid="6174142840934095093">"No medida"</string> - <string name="select_logd_size_title" msgid="1604578195914595173">"Tamaños del búfer para registrar"</string> + <string name="select_logd_size_title" msgid="1604578195914595173">"Tamaños del búfer de registro"</string> <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"Elige el tamaño del Logger por búfer"</string> <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"¿Borrar almacenamiento continuo del registrador?"</string> <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"Cuando ya no supervisamos la actividad con el registrador de forma continua, estamos obligados a borrar los datos del registrador almacenados en el dispositivo."</string> @@ -347,7 +347,7 @@ <string name="hdcp_checking_dialog_title" msgid="7691060297616217781">"Establecer comprobación HDCP"</string> <string name="debug_debugging_category" msgid="535341063709248842">"Depuración"</string> <string name="debug_app" msgid="8903350241392391766">"Elegir aplicación de depuración"</string> - <string name="debug_app_not_set" msgid="1934083001283807188">"Aplicación de depuración no configurada"</string> + <string name="debug_app_not_set" msgid="1934083001283807188">"Aplicación de depuración no establecida"</string> <string name="debug_app_set" msgid="6599535090477753651">"Aplicación de depuración: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="select_application" msgid="2543228890535466325">"Selecciona una aplicación"</string> <string name="no_application" msgid="9038334538870247690">"Ninguna"</string> @@ -366,20 +366,20 @@ <string name="show_touches_summary" msgid="3692861665994502193">"Muestra la ubicación de los toques en la pantalla"</string> <string name="show_screen_updates" msgid="2078782895825535494">"Mostrar cambios de superficies"</string> <string name="show_screen_updates_summary" msgid="2126932969682087406">"Hace parpadear todas las superficies de la ventana cuando se actualizan"</string> - <string name="show_hw_screen_updates" msgid="2021286231267747506">"Ver cambios de vista"</string> + <string name="show_hw_screen_updates" msgid="2021286231267747506">"Ver actualizaciones de vista"</string> <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"Hacer parpadear las vistas dentro de las ventanas cuando se dibujan"</string> <string name="show_hw_layers_updates" msgid="5268370750002509767">"Ver actualizaciones de capas de hardware"</string> <string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"Hacer parpadear las capas de hardware en verde cuando se actualizan"</string> <string name="debug_hw_overdraw" msgid="8944851091008756796">"Depurar sobredibujos de GPU"</string> <string name="disable_overlays" msgid="4206590799671557143">"Inhabilitar superposiciones de hardware"</string> - <string name="disable_overlays_summary" msgid="1954852414363338166">"Usar siempre la GPU para componer pantallas"</string> + <string name="disable_overlays_summary" msgid="1954852414363338166">"Usa siempre la GPU para componer pantallas"</string> <string name="simulate_color_space" msgid="1206503300335835151">"Simular espacio de color"</string> <string name="enable_opengl_traces_title" msgid="4638773318659125196">"Habilitar seguimiento OpenGL"</string> <string name="usb_audio_disable_routing" msgid="3367656923544254975">"Inhabilitar enrutamiento de audio por USB"</string> <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"Inhabilita el enrutamiento automático a periféricos de audio USB"</string> <string name="debug_layout" msgid="1659216803043339741">"Mostrar límites de diseño"</string> <string name="debug_layout_summary" msgid="8825829038287321978">"Muestra límites de vídeo, márgenes, etc."</string> - <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Forzar dirección de diseño RTL"</string> + <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Forzar dirección RTL"</string> <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Fuerza la dirección RTL para todos los idiomas"</string> <string name="window_blurs" msgid="6831008984828425106">"Difuminar ventanas"</string> <string name="force_msaa" msgid="4081288296137775550">"Forzar MSAA 4x"</string> @@ -387,7 +387,7 @@ <string name="show_non_rect_clip" msgid="7499758654867881817">"Depurar operaciones de recorte no rectangulares"</string> <string name="track_frame_time" msgid="522674651937771106">"Trazar la renderización de HWUI"</string> <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Activar capas de depuración de GPU"</string> - <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Permite cargar capas de depuración de GPU para aplicaciones de depuración"</string> + <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Permite cargar capas de depuración de GPU en aplicaciones de depuración"</string> <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Habilitar registro de proveedor detallado"</string> <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Incluye otros registros de proveedor específicos del dispositivo en informes de errores, lo que puede añadir información privada, usar más batería u ocupar más espacio de almacenamiento."</string> <string name="window_animation_scale_title" msgid="5236381298376812508">"Escala de animación de ventana"</string> @@ -399,7 +399,7 @@ <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"Destruye actividades cuando el usuario deja de usarlas"</string> <string name="app_process_limit_title" msgid="8361367869453043007">"Límitar procesos en segundo plano"</string> <string name="show_all_anrs" msgid="9160563836616468726">"Mostrar ANR en segundo plano"</string> - <string name="show_all_anrs_summary" msgid="8562788834431971392">"Muestra el cuadro de diálogo de que la aplicación no responde para aplicaciones en segundo plano"</string> + <string name="show_all_anrs_summary" msgid="8562788834431971392">"Muestra un cuadro de diálogo que informa de que la aplicación no responde en aplicaciones en segundo plano"</string> <string name="show_notification_channel_warnings" msgid="3448282400127597331">"Ver advertencias del canal de notificaciones"</string> <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"Muestra una advertencia en pantalla cuando una aplicación publica una notificación sin un canal válido"</string> <string name="force_allow_on_external" msgid="9187902444231637880">"Forzar permitir aplicaciones en almacenamiento externo"</string> @@ -552,7 +552,7 @@ <string name="help_label" msgid="3528360748637781274">"Ayuda y comentarios"</string> <string name="storage_category" msgid="2287342585424631813">"Almacenamiento"</string> <string name="shared_data_title" msgid="1017034836800864953">"Datos compartidos"</string> - <string name="shared_data_summary" msgid="5516326713822885652">"Ver y modificar los datos compartidos"</string> + <string name="shared_data_summary" msgid="5516326713822885652">"Consulta y modifica datos compartidos"</string> <string name="shared_data_no_blobs_text" msgid="3108114670341737434">"No hay datos compartidos de este usuario."</string> <string name="shared_data_query_failure_text" msgid="3489828881998773687">"No se han podido generar datos compartidos. Inténtalo de nuevo."</string> <string name="blob_id_text" msgid="8680078988996308061">"ID de datos compartidos: <xliff:g id="BLOB_ID">%d</xliff:g>"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Escanear código QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Para empezar a escuchar, centra el código QR aquí abajo"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"El formato del código QR no es válido"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"¿Dejar de emitir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Si emites <xliff:g id="SWITCHAPP">%1$s</xliff:g> o cambias la salida, tu emisión actual se detendrá"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Emitir <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Cambiar salida"</string> </resources> diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml index 996b92fdb457..29376f30c1fb 100644 --- a/packages/SettingsLib/res/values-et/strings.xml +++ b/packages/SettingsLib/res/values-et/strings.xml @@ -47,7 +47,7 @@ <string name="wifi_security_sae" msgid="3644520541721422843">"WPA3-Personal"</string> <string name="wifi_security_psk_sae" msgid="8135104122179904684">"WPA2/WPA3-Personal"</string> <string name="wifi_security_none_owe" msgid="5241745828327404101">"Puudub / Täiustatud avamine"</string> - <string name="wifi_security_owe" msgid="3343421403561657809">"Täiustatud avamine"</string> + <string name="wifi_security_owe" msgid="3343421403561657809">"Enhanced Open"</string> <string name="wifi_security_eap_suiteb" msgid="415842785991698142">"WPA3-Enterprise (192-bitine)"</string> <string name="wifi_remembered" msgid="3266709779723179188">"Salvestatud"</string> <string name="wifi_disconnected" msgid="7054450256284661757">"Pole ühendatud"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR-koodi skannimine"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Kuulamise alustamiseks paigutage QR-kood allpool keskele"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR-kood ei ole sobilik vorming"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Kas peatada rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> ülekandmine?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Kui kannate rakendust <xliff:g id="SWITCHAPP">%1$s</xliff:g> üle või muudate väljundit, peatatakse teie praegune ülekanne"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Rakenduse <xliff:g id="SWITCHAPP">%1$s</xliff:g> ülekandmine"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Väljundi muutmine"</string> </resources> diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml index d6741dc13364..5386c3513fa4 100644 --- a/packages/SettingsLib/res/values-eu/strings.xml +++ b/packages/SettingsLib/res/values-eu/strings.xml @@ -286,7 +286,7 @@ <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Erakutsi Bluetooth bidezko gailuak izenik gabe"</string> <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Desgaitu bolumen absolutua"</string> <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gaitu Gabeldorsche"</string> - <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCP bertsioa"</string> + <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"Bluetooth AVRCParen bertsioa"</string> <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Hautatu Bluetooth AVRCP bertsioa"</string> <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Bluetooth MAParen bertsioa"</string> <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Hautatu Bluetooth MAParen bertsioa"</string> @@ -372,14 +372,14 @@ <string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"Distirarazi hardware-geruzak berdez haiek eguneratzean"</string> <string name="debug_hw_overdraw" msgid="8944851091008756796">"Araztu GPU gainidazketa"</string> <string name="disable_overlays" msgid="4206590799671557143">"Desgaitu HW gainjartzeak"</string> - <string name="disable_overlays_summary" msgid="1954852414363338166">"Erabili beti GPU pantaila-muntaietarako"</string> + <string name="disable_overlays_summary" msgid="1954852414363338166">"Erabili beti GPUa pantaila-muntaietarako"</string> <string name="simulate_color_space" msgid="1206503300335835151">"Simulatu kolore-eremua"</string> <string name="enable_opengl_traces_title" msgid="4638773318659125196">"Gaitu OpenGL aztarnak"</string> <string name="usb_audio_disable_routing" msgid="3367656923544254975">"Desgaitu USB bidez audioa bideratzeko aukera"</string> <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"Desgaitu USB bidezko audio-gailuetara automatikoki bideratzeko aukera"</string> <string name="debug_layout" msgid="1659216803043339741">"Erakutsi diseinu-mugak"</string> <string name="debug_layout_summary" msgid="8825829038287321978">"Erakutsi kliparen mugak, marjinak, etab."</string> - <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Behartu eskuin-ezker norabidea"</string> + <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Eskuinetik ezkerrerako norabidea"</string> <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Behartu pantaila-diseinuaren norabidea eskuin-ezker izatera lurraldeko ezarpen guztiekin"</string> <string name="window_blurs" msgid="6831008984828425106">"Gaitu leiho-lausotzeak"</string> <string name="force_msaa" msgid="4081288296137775550">"Behartu 4x MSAA"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Eskaneatu QR kodea"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Entzuten hasteko, zentratu beheko QR kodea"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR kodearen formatuak ez du balio"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioaren audioa igortzeari utzi nahi diozu?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> aplikazioaren audioa igortzen baduzu, edo audio-irteera aldatzen baduzu, une hartako igorpena eten egingo da"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Igorri <xliff:g id="SWITCHAPP">%1$s</xliff:g> aplikazioaren audioa"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Aldatu audio-irteera"</string> </resources> diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml index 95ea4c25dae8..740e1e69906f 100644 --- a/packages/SettingsLib/res/values-fa/strings.xml +++ b/packages/SettingsLib/res/values-fa/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"اسکن رمزینه پاسخسریع"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"برای گوش دادن، رمزینه پاسخسریع زیر را در مرکز کادر قرار دهید"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"قالب رمزینه پاسخسریع معتبر نیست"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"همهفرستی <xliff:g id="APP_NAME">%1$s</xliff:g> متوقف شود؟"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"اگر <xliff:g id="SWITCHAPP">%1$s</xliff:g> را همهفرستی کنید یا خروجی را تغییر دهید، همهفرستی کنونی متوقف خواهد شد"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"همهفرستی <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"تغییر خروجی"</string> </resources> diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index dd0e50ed5239..32c52412359b 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Skannaa QR-koodi"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Aloita kuuntelu keskittämällä alla olevaan QR-koodiin"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR-koodin muoto ei kelpaa"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Lopetetaanko <xliff:g id="APP_NAME">%1$s</xliff:g>-sovelluksen lähettäminen?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Jos lähetät <xliff:g id="SWITCHAPP">%1$s</xliff:g>-sovellusta tai muutat ulostuloa, nykyinen lähetyksesi loppuu"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Lähetä <xliff:g id="SWITCHAPP">%1$s</xliff:g>-sovellusta"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Muuta ulostuloa"</string> </resources> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index a4d9ccc52a76..e1e731f601e7 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -507,7 +507,7 @@ <string name="screen_zoom_summary_extremely_large" msgid="1438045624562358554">"La plus grande"</string> <string name="screen_zoom_summary_custom" msgid="3468154096832912210">"Personnalisée (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string> <string name="content_description_menu_button" msgid="6254844309171779931">"Menu"</string> - <string name="retail_demo_reset_message" msgid="5392824901108195463">"Entrez m. passe pour réinit. en mode démo"</string> + <string name="retail_demo_reset_message" msgid="5392824901108195463">"Entrez m. passe pour réinit. en mode Démo"</string> <string name="retail_demo_reset_next" msgid="3688129033843885362">"Suivant"</string> <string name="retail_demo_reset_title" msgid="1866911701095959800">"Mot de passe obligatoire"</string> <string name="active_input_method_subtypes" msgid="4232680535471633046">"Modes de saisie actifs"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Numériser le code QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Pour commencer à écouter, centrez le code QR ci-dessous"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"Le format du code QR est incorrect"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Arrêter la diffusion de <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Si vous diffusez <xliff:g id="SWITCHAPP">%1$s</xliff:g> ou changez la sortie, votre diffusion actuelle s\'arrêtera"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Diffuser <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Changer la sortie"</string> </resources> diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index 921cf2b3b892..e635464d0926 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Scanner un code QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Pour commencer à écouter, centrez le code QR ci-dessous"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"Le format de code QR n\'est pas valide"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Arrêter la diffusion de <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Si vous diffusez <xliff:g id="SWITCHAPP">%1$s</xliff:g> ou que vous modifiez le résultat, votre annonce actuelle s\'arrêtera"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Diffuser <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Modifier le résultat"</string> </resources> diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml index bbb4285b4834..f5ea9d473021 100644 --- a/packages/SettingsLib/res/values-gl/strings.xml +++ b/packages/SettingsLib/res/values-gl/strings.xml @@ -312,7 +312,7 @@ <string name="wifi_display_certification_summary" msgid="8111151348106907513">"Mostra opcións para o certificado de visualización sen fíos"</string> <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Aumenta o nivel de rexistro da wifi, móstrao por SSID RSSI no selector de wifi"</string> <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Reduce o consumo de batería e mellora o rendemento da rede"</string> - <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Cando este modo está activado, o enderezo MAC pode cambiar cada vez que se este dispositivo se conecta a unha rede que teña activada a orde aleatoria de enderezos MAC."</string> + <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Cando este modo está activado, o enderezo MAC pode cambiar cada vez que este dispositivo se conecte a unha rede que teña activada a orde aleatoria de enderezos MAC"</string> <string name="wifi_metered_label" msgid="8737187690304098638">"Rede sen tarifa plana"</string> <string name="wifi_unmetered_label" msgid="6174142840934095093">"Rede con tarifa plana"</string> <string name="select_logd_size_title" msgid="1604578195914595173">"Tamaño dos búfers do rexistrador"</string> @@ -359,37 +359,37 @@ <string name="media_category" msgid="8122076702526144053">"Multimedia"</string> <string name="debug_monitoring_category" msgid="1597387133765424994">"Supervisión"</string> <string name="strict_mode" msgid="889864762140862437">"Modo estrito activado"</string> - <string name="strict_mode_summary" msgid="1838248687233554654">"Ilumínase se as aplicacións tardan moito no proceso principal"</string> + <string name="strict_mode_summary" msgid="1838248687233554654">"A pantalla ilumínase se as aplicacións tardan moito no proceso principal"</string> <string name="pointer_location" msgid="7516929526199520173">"Localización do punteiro"</string> <string name="pointer_location_summary" msgid="957120116989798464">"Superpón os datos dos toques na pantalla"</string> <string name="show_touches" msgid="8437666942161289025">"Mostrar toques"</string> <string name="show_touches_summary" msgid="3692861665994502193">"Mostra a localización dos toques na pantalla"</string> - <string name="show_screen_updates" msgid="2078782895825535494">"Cambios de superficie"</string> + <string name="show_screen_updates" msgid="2078782895825535494">"Mostrar cambios de superficie"</string> <string name="show_screen_updates_summary" msgid="2126932969682087406">"Ilumina as superficies de ventás ao actualizarse"</string> <string name="show_hw_screen_updates" msgid="2021286231267747506">"Mostrar actualizacións"</string> <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"Ilumina as vistas das ventás creadas"</string> <string name="show_hw_layers_updates" msgid="5268370750002509767">"Ver actualizacións de capas de hardware"</string> <string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"Ilumina as capas de hardware en verde ao actualizárense"</string> - <string name="debug_hw_overdraw" msgid="8944851091008756796">"Depurar superposición GPU"</string> + <string name="debug_hw_overdraw" msgid="8944851091008756796">"Depurar superposición de GPU"</string> <string name="disable_overlays" msgid="4206590799671557143">"Desactivar superposicións de hardware"</string> - <string name="disable_overlays_summary" msgid="1954852414363338166">"Utiliza sempre GPU para a composición da pantalla"</string> + <string name="disable_overlays_summary" msgid="1954852414363338166">"Utiliza sempre a GPU para a composición da pantalla"</string> <string name="simulate_color_space" msgid="1206503300335835151">"Simular espazo de cor"</string> <string name="enable_opengl_traces_title" msgid="4638773318659125196">"Activar rastros OpenGL"</string> - <string name="usb_audio_disable_routing" msgid="3367656923544254975">"Desactivar encamiñamento audio USB"</string> + <string name="usb_audio_disable_routing" msgid="3367656923544254975">"Desactivar encamiñamento de audio por USB"</string> <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"Desactiva o encamiñamento automático a periféricos de audio USB"</string> <string name="debug_layout" msgid="1659216803043339741">"Mostrar límites de deseño"</string> <string name="debug_layout_summary" msgid="8825829038287321978">"Mostra os límites dos clips, as marxes etc."</string> <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Forzar dirección do deseño RTL"</string> - <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Forza a dirección de pantalla a RTL (dereita a esquerda) para todas as configuración rexionais"</string> - <string name="window_blurs" msgid="6831008984828425106">"Permitir desenfoque ventá"</string> + <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Forza a dirección de pantalla de dereita a esquerda para todas as opcións de configuración rexionais"</string> + <string name="window_blurs" msgid="6831008984828425106">"Permitir desenfoque de ventás"</string> <string name="force_msaa" msgid="4081288296137775550">"Forzar MSAA 4x"</string> <string name="force_msaa_summary" msgid="9070437493586769500">"Activa MSAA 4x en aplicacións OpenGL ES 2.0"</string> - <string name="show_non_rect_clip" msgid="7499758654867881817">"Depurar accións recorte non rectangulares"</string> - <string name="track_frame_time" msgid="522674651937771106">"Perfil procesamento HWUI"</string> + <string name="show_non_rect_clip" msgid="7499758654867881817">"Depurar accións de recorte non rectangulares"</string> + <string name="track_frame_time" msgid="522674651937771106">"Perfil de procesamento de HWUI"</string> <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Activar depuración da GPU"</string> - <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Permite capas da GPU para apps de depuración"</string> + <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Permite cargar capas de depuración da GPU para aplicacións de depuración"</string> <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Activar rexistro de provedores"</string> - <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Inclúe outros rexistros de provedores específicos do dispositivo en informes de erros; pode conter información privada, consumir máis batería e ocupar máis espazo almacenamento"</string> + <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Inclúe outros rexistros de provedores específicos do dispositivo en informes de erros; pode conter información privada, consumir máis batería e ocupar máis espazo de almacenamento"</string> <string name="window_animation_scale_title" msgid="5236381298376812508">"Escala de animación da ventá"</string> <string name="transition_animation_scale_title" msgid="1278477690695439337">"Escala animación-transición"</string> <string name="animator_duration_scale_title" msgid="7082913931326085176">"Escala duración animador"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Escanear código QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Para comezar a escoitar audio, encadra o seguinte código QR"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"O formato do código QR non é válido"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Queres deixar de emitir contido a través de <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Se emites contido a través de <xliff:g id="SWITCHAPP">%1$s</xliff:g> ou cambias de saída, a emisión en curso deterase"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Emitir contido a través de <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Cambiar de saída"</string> </resources> diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml index 88e22a15374c..a9c4b69b261a 100644 --- a/packages/SettingsLib/res/values-gu/strings.xml +++ b/packages/SettingsLib/res/values-gu/strings.xml @@ -185,7 +185,7 @@ <string name="launch_defaults_none" msgid="8049374306261262709">"કોઈ ડિફૉલ્ટ સેટ કરેલા નથી"</string> <string name="tts_settings" msgid="8130616705989351312">"ટેક્સ્ટ ટૂ સ્પીચ સેટિંગ"</string> <string name="tts_settings_title" msgid="7602210956640483039">"ટેક્સ્ટ ટુ સ્પીચ આઉટપુટ"</string> - <string name="tts_default_rate_title" msgid="3964187817364304022">"વાણી દર"</string> + <string name="tts_default_rate_title" msgid="3964187817364304022">"સ્પીચ રેટ"</string> <string name="tts_default_rate_summary" msgid="3781937042151716987">"ટેક્સ્ટ બોલાયેલ છે તે ઝડપ"</string> <string name="tts_default_pitch_title" msgid="6988592215554485479">"પિચ"</string> <string name="tts_default_pitch_summary" msgid="9132719475281551884">"સિન્થેસાઇઝ કરેલ વાણીના ટોન પર અસર કરે છે"</string> @@ -406,8 +406,8 @@ <string name="force_allow_on_external_summary" msgid="8525425782530728238">"મેનિફેસ્ટ મૂલ્યોને ધ્યાનમાં લીધા સિવાય, કોઈપણ ઍપને બાહ્ય સ્ટોરેજ પર લખાવા માટે લાયક બનાવે છે"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"પ્રવૃત્તિઓને ફરીથી કદ યોગ્ય થવા માટે ફરજ પાડો"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"મૅનિફેસ્ટ મૂલ્યોને ધ્યાનમાં લીધા સિવાય, તમામ પ્રવૃત્તિઓને મલ્ટી-વિન્ડો માટે ફરીથી કદ બદલી શકે તેવી બનાવો."</string> - <string name="enable_freeform_support" msgid="7599125687603914253">"ફ્રિફોર્મ વિંડોઝ ચાલુ કરો"</string> - <string name="enable_freeform_support_summary" msgid="1822862728719276331">"પ્રાયોગિક ફ્રિફોર્મ વિંડોઝ માટે સમર્થનને ચાલુ કરો."</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"ફ્રીફોર્મ વિન્ડો ચાલુ કરો"</string> + <string name="enable_freeform_support_summary" msgid="1822862728719276331">"પ્રાયોગિક ફ્રીફોર્મ વિન્ડો માટે સપોર્ટને ચાલુ કરો."</string> <string name="local_backup_password_title" msgid="4631017948933578709">"ડેસ્કટૉપ બૅકઅપ પાસવર્ડ"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"ડેસ્કટૉપ સંપૂર્ણ બૅકઅપ હાલમાં સુરક્ષિત નથી"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"ડેસ્કટૉપ સંપૂર્ણ બેકઅપ્સ માટેનો પાસવર્ડ બદલવા અથવા દૂર કરવા માટે ટૅચ કરો"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR કોડ સ્કૅન કરો"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"સાંભળવાનું શરૂ કરવા માટે, QR કોડને નીચે ફ્રેમની મધ્યમાં લાવો"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"આ QR કોડ માન્ય ફૉર્મેટમાં નથી"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> બ્રોડકાસ્ટ કરવાનું રોકીએ?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"જો તમે <xliff:g id="SWITCHAPP">%1$s</xliff:g> બ્રોડકાસ્ટ કરો અથવા આઉટપુટ બદલો, તો તમારું હાલનું બ્રોડકાસ્ટ બંધ થઈ જશે"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> બ્રોડકાસ્ટ કરો"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"આઉટપુટ બદલો"</string> </resources> diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml index 4fd8d64883df..a449773611a1 100644 --- a/packages/SettingsLib/res/values-hi/arrays.xml +++ b/packages/SettingsLib/res/values-hi/arrays.xml @@ -55,7 +55,7 @@ </string-array> <string-array name="hdcp_checking_summaries"> <item msgid="4045840870658484038">"कभी भी HDCP जाँच का उपयोग न करें"</item> - <item msgid="8254225038262324761">"HDCP जांच का उपयोग सिर्फ़ डीआरएम कॉन्टेंट के लिए करें"</item> + <item msgid="8254225038262324761">"HDCP जांच का इस्तेमाल सिर्फ़ डीआरएम कॉन्टेंट के लिए करें"</item> <item msgid="6421717003037072581">"हमेशा HDCP जाँच का उपयोग करें"</item> </string-array> <string-array name="bt_hci_snoop_log_entries"> @@ -64,7 +64,7 @@ <item msgid="2779123106632690576">"चालू है"</item> </string-array> <string-array name="bluetooth_avrcp_versions"> - <item msgid="6603880723315236832">"एवीआरसीपी 1.5 (डिफ़ॉल्ट)"</item> + <item msgid="6603880723315236832">"AVRCP 1.5 (डिफ़ॉल्ट)"</item> <item msgid="1637054408779685086">"AVRCP 1.3"</item> <item msgid="5896162189744596291">"एवीआरसीपी 1.4"</item> <item msgid="7556896992111771426">"AVRCP 1.6"</item> @@ -94,7 +94,7 @@ <item msgid="3825367753087348007">"LDAC"</item> </string-array> <string-array name="bluetooth_a2dp_codec_summaries"> - <item msgid="8868109554557331312">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item> + <item msgid="8868109554557331312">"सिस्टम से चुने जाने का इस्तेमाल करें (डिफ़ॉल्ट)"</item> <item msgid="9024885861221697796">"SBC"</item> <item msgid="4688890470703790013">"AAC"</item> <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ऑडियो"</item> @@ -109,7 +109,7 @@ <item msgid="8887519571067543785">"96.0 kHz"</item> </string-array> <string-array name="bluetooth_a2dp_codec_sample_rate_summaries"> - <item msgid="2284090879080331090">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item> + <item msgid="2284090879080331090">"सिस्टम से चुने जाने का इस्तेमाल करें (डिफ़ॉल्ट)"</item> <item msgid="1872276250541651186">"44.1 kHz"</item> <item msgid="8736780630001704004">"48.0 kHz"</item> <item msgid="7698585706868856888">"88.2 kHz"</item> @@ -122,7 +122,7 @@ <item msgid="1212577207279552119">"32 बिट/नमूना"</item> </string-array> <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries"> - <item msgid="9196208128729063711">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item> + <item msgid="9196208128729063711">"सिस्टम से चुने जाने का इस्तेमाल करें (डिफ़ॉल्ट)"</item> <item msgid="1084497364516370912">"16 बिट/नमूना"</item> <item msgid="2077889391457961734">"24 बिट/नमूना"</item> <item msgid="3836844909491316925">"32 बिट/नमूना"</item> @@ -133,7 +133,7 @@ <item msgid="927546067692441494">"स्टीरियो"</item> </string-array> <string-array name="bluetooth_a2dp_codec_channel_mode_summaries"> - <item msgid="1997302811102880485">"सिस्टम चुनाव का उपयोग करें (डिफ़ॉल्ट)"</item> + <item msgid="1997302811102880485">"सिस्टम से चुने जाने का इस्तेमाल करें (डिफ़ॉल्ट)"</item> <item msgid="8005696114958453588">"मोनो"</item> <item msgid="1333279807604675720">"स्टीरियो"</item> </string-array> @@ -173,7 +173,7 @@ <item msgid="409235464399258501">"बंद"</item> <item msgid="4195153527464162486">"64K प्रति लॉग बफ़र"</item> <item msgid="7464037639415220106">"256K प्रति लॉग बफ़र"</item> - <item msgid="8539423820514360724">"1 एमबी प्रति लॉग बफ़र"</item> + <item msgid="8539423820514360724">"1M प्रति लॉग बफ़र"</item> <item msgid="1984761927103140651">"4M प्रति लॉग बफ़र"</item> <item msgid="2983219471251787208">"8 एमबी प्रति लॉग बफ़र"</item> </string-array> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index 859c8764f8ca..02b78c16aabc 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -234,7 +234,7 @@ <string name="apn_settings_not_available" msgid="1147111671403342300">"ऐक्सेस पॉइंट के नाम की सेटिंग इस उपयोगकर्ता के लिए मौजूद नहीं हैं"</string> <string name="enable_adb" msgid="8072776357237289039">"यूएसबी डीबग करना"</string> <string name="enable_adb_summary" msgid="3711526030096574316">"डीबग मोड जब यूएसबी कनेक्ट किया गया हो"</string> - <string name="clear_adb_keys" msgid="3010148733140369917">"यूएसबी डीबग करने की मंज़ूरी रद्द करें"</string> + <string name="clear_adb_keys" msgid="3010148733140369917">"यूएसबी डीबग करने की मंज़ूरी निरस्त करें"</string> <string name="enable_adb_wireless" msgid="6973226350963971018">"वॉयरलेस डीबगिंग"</string> <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"डिवाइस के वाई-फ़ाई से कनेक्ट हाेने पर, डीबग मोड चालू करें"</string> <string name="adb_wireless_error" msgid="721958772149779856">"गड़बड़ी"</string> @@ -267,35 +267,35 @@ <string name="bugreport_in_power_summary" msgid="1885529649381831775">"गड़बड़ी की रिपोर्ट लेने के लिए पावर मेन्यू में कोई बटन दिखाएं"</string> <string name="keep_screen_on" msgid="1187161672348797558">"स्क्रीन को चालू रखें"</string> <string name="keep_screen_on_summary" msgid="1510731514101925829">"चार्ज करते समय स्क्रीन कभी भी कम बैटरी मोड में नहीं जाएगी"</string> - <string name="bt_hci_snoop_log" msgid="7291287955649081448">"ब्लूटूथ एचसीआई स्नूप लॉग चालू करें"</string> + <string name="bt_hci_snoop_log" msgid="7291287955649081448">"ब्लूटूथ HCI स्नूप लॉग चालू करें"</string> <string name="bt_hci_snoop_log_summary" msgid="6808538971394092284">"ब्लूटूथ पैकेट कैप्चर करें. (यह सेटिंग बदलने के बाद ब्लूटूथ टॉगल करें)"</string> <string name="oem_unlock_enable" msgid="5334869171871566731">"OEM अनलॉक करना"</string> <string name="oem_unlock_enable_summary" msgid="5857388174390953829">"बूटलोडर को अनलाॅक किए जाने की अनुमति दें"</string> <string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"OEM अनलॉक करने की अनुमति दें?"</string> <string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"चेतावनी: इस सेटिंग के चालू रहने पर डिवाइस सुरक्षा सुविधाएं इस डिवाइस पर काम नहीं करेंगी."</string> - <string name="mock_location_app" msgid="6269380172542248304">"जगह की नकली जानकारी देने के लिए ऐप चुनें"</string> - <string name="mock_location_app_not_set" msgid="6972032787262831155">"जगह की नकली जानकारी देने के लिए ऐप सेट नहीं है"</string> - <string name="mock_location_app_set" msgid="4706722469342913843">"जगह की नकली जानकारी देने वाला ऐप: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> + <string name="mock_location_app" msgid="6269380172542248304">"जगह की दिखावटी जानकारी देने के लिए ऐप्लिकेशन चुनें"</string> + <string name="mock_location_app_not_set" msgid="6972032787262831155">"जगह की दिखावटी जानकारी देने के लिए ऐप सेट नहीं है"</string> + <string name="mock_location_app_set" msgid="4706722469342913843">"जगह की दिखावटी जानकारी देने वाला ऐप: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="debug_networking_category" msgid="6829757985772659599">"नेटवर्किंग"</string> <string name="wifi_display_certification" msgid="1805579519992520381">"वायरलेस डिसप्ले सर्टिफ़िकेशन"</string> <string name="wifi_verbose_logging" msgid="1785910450009679371">"वाई-फ़ाई वर्बोस लॉगिंग चालू करें"</string> - <string name="wifi_scan_throttling" msgid="2985624788509913617">"वाई-फ़ाई के लिए स्कैन की संख्या कम करें"</string> + <string name="wifi_scan_throttling" msgid="2985624788509913617">"वाई-फ़ाई के लिए स्कैन थ्रॉटलिंग करें"</string> <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"थोड़े समय के लिए वाई-फ़ाई नेटवर्क से जुड़ने पर MAC पता बदलने की सुविधा"</string> <string name="mobile_data_always_on" msgid="8275958101875563572">"मोबाइल डेटा हमेशा चालू"</string> <string name="tethering_hardware_offload" msgid="4116053719006939161">"हार्डवेयर से तेज़ी लाने के लिए टेदर करें"</string> <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"बिना नाम वाले ब्लूटूथ डिवाइस दिखाएं"</string> <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"ब्लूटूथ से आवाज़ के कंट्रोल की सुविधा रोकें"</string> <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorsche चालू करें"</string> - <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"ब्लूटूथ एवीआरसीपी वर्शन"</string> + <string name="bluetooth_select_avrcp_version_string" msgid="1710571610177659127">"ब्लूटूथ AVRCP वर्शन"</string> <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"ब्लूटूथ AVRCP वर्शन चुनें"</string> <string name="bluetooth_select_map_version_string" msgid="526308145174175327">"ब्लूटूथ का MAP वर्शन"</string> <string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"ब्लूटूथ का MAP वर्शन चुनें"</string> <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"ब्लूटूथ ऑडियो कोडेक"</string> <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"ब्लूटूथ ऑडियो कोडेक का\nविकल्प चालू करें"</string> - <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ब्लूटूथ ऑडियो नमूना दर"</string> + <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"ब्लूटूथ ऑडियो सैंपल रेट"</string> <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"ब्लूटूथ ऑडियो कोडेक का\nयह विकल्प चालू करें: सैंपल की दर"</string> <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"धूसर किया गया का मतलब है कि फ़ोन या हेडसेट पर काम नहीं करता"</string> - <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"ब्लूटूथ ऑडियो बिट प्रति नमूना"</string> + <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"हर सैंपल के लिए ब्लूटूथ ऑडियो बिट"</string> <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ब्लूटूथ ऑडियो कोडेक का\nयह विकल्प चालू करें: हर सैंपल के लिए बिट की संख्या"</string> <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ब्लूटूथ ऑडियो चैनल मोड"</string> <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="2076949781460359589">"ब्लूटूथ ऑडियो कोडेक का\nयह विकल्प चालू करें: चैनल मोड"</string> @@ -310,12 +310,12 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="6564868953748514595">"डीएनएस सेवा देने वाले का होस्टनाम डालें"</string> <string name="private_dns_mode_provider_failure" msgid="8356259467861515108">"कनेक्ट नहीं हो सका"</string> <string name="wifi_display_certification_summary" msgid="8111151348106907513">"वायरलेस डिसप्ले सर्टिफ़िकेशन के विकल्प दिखाएं"</string> - <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"वाई-फ़ाई लॉगिंग का स्तर बढ़ाएं, वाई-फ़ाई पिकर में प्रति SSID RSSI दिखाएं"</string> + <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"वाई-फ़ाई लॉगिंग लेवल बढ़ाएं, वाई-फ़ाई पिकर में हर SSID के लिए RSSI दिखाएं"</string> <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"बैटरी की खपत कम और नेटवर्क की परफ़ॉर्मेंस बेहतर होती है"</string> <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"जब यह मोड चालू होता है, तब नेटवर्क से कनेक्ट होने पर हर बार इस डिवाइस का MAC पता बदल सकता है. ऐसा तब होता है, जब डिवाइस किसी ऐसे नेटवर्क से जुड़ता है जिस पर MAC पता बदलने की सुविधा चालू होती है."</string> <string name="wifi_metered_label" msgid="8737187690304098638">"डेटा इस्तेमाल करने की सीमा तय की गई है"</string> <string name="wifi_unmetered_label" msgid="6174142840934095093">"डेटा इस्तेमाल करने की सीमा तय नहीं की गई है"</string> - <string name="select_logd_size_title" msgid="1604578195914595173">"लॉगर बफ़र आकार"</string> + <string name="select_logd_size_title" msgid="1604578195914595173">"लॉगर बफ़र साइज़"</string> <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"प्रति लॉग बफ़र लॉगर आकार चुनें"</string> <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"लॉगर सतत मेमोरी साफ़ करें?"</string> <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"जब हम सतत लॉगर के साथ निगरानी करना बंद कर देते हैं, तो हमें आपके डिवाइस पर मौजूद लॉगर डेटा को मिटाने की आवश्यकता होती है."</string> @@ -336,7 +336,7 @@ <string name="dev_settings_warning_title" msgid="8251234890169074553">"विकास सेटिंग की अनुमति दें?"</string> <string name="dev_settings_warning_message" msgid="37741686486073668">"ये सेटिंग केवल विकास संबंधी उपयोग के प्रयोजन से हैं. वे आपके डिवाइस और उस पर स्थित ऐप्लिकेशन को खराब कर सकती हैं या उनके दुर्व्यवहार का कारण हो सकती हैं."</string> <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"यूएसबी पर ऐप्लिकेशन की पुष्टि करें"</string> - <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"नुकसानदेह व्यवहार के लिए ADB/ADT से इंस्टॉल किए गए ऐप्लिकेशन जांचें."</string> + <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"नुकसान पहुंचाने वाली गतिविधियों के लिए ADB/ADT से इंस्टॉल किए गए ऐप्लिकेशन जांचें."</string> <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"बिना नाम वाले ब्लूटूथ डिवाइस (सिर्फ़ MAC पते वाले) दिखाए जाएंगे"</string> <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"दूर के डिवाइस पर आवाज़ बहुत बढ़ जाने या उससे कंट्रोल हटने जैसी समस्याएं होने पर, यह ब्लूटूथ के ज़रिए आवाज़ के कंट्रोल की सुविधा रोक देता है."</string> <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"ब्लूटूथ सेटिंग में Gabeldorsche सुविधा को चालू करता है."</string> @@ -358,14 +358,14 @@ <string name="debug_hw_drawing_category" msgid="5830815169336975162">"हार्डवेयर ऐक्सेलरेटेड रेंडरिंग"</string> <string name="media_category" msgid="8122076702526144053">"मीडिया"</string> <string name="debug_monitoring_category" msgid="1597387133765424994">"निगरानी"</string> - <string name="strict_mode" msgid="889864762140862437">"सख्त मोड चालू किया गया"</string> + <string name="strict_mode" msgid="889864762140862437">"स्ट्रिक्ट मोड चालू किया गया"</string> <string name="strict_mode_summary" msgid="1838248687233554654">"थ्रेड पर लंबा प्रोसेस होने पर स्क्रीन फ़्लैश करें"</string> <string name="pointer_location" msgid="7516929526199520173">"पॉइंटर की जगह"</string> <string name="pointer_location_summary" msgid="957120116989798464">"मौजूदा टच डेटा दिखाने वाला स्क्रीन ओवरले"</string> <string name="show_touches" msgid="8437666942161289025">"टैप दिखाएं"</string> <string name="show_touches_summary" msgid="3692861665994502193">"टैप के लिए विज़ुअल फ़ीडबैक दिखाएं"</string> <string name="show_screen_updates" msgid="2078782895825535494">"सर्फ़ेस अपडेट दिखाएं"</string> - <string name="show_screen_updates_summary" msgid="2126932969682087406">"अपडेट होने पर पूरे विंडो सर्फ़ेस को फ़्लैश करें"</string> + <string name="show_screen_updates_summary" msgid="2126932969682087406">"अपडेट होने पर पूरे विंडो सर्फ़ेस फ़्लैश करें"</string> <string name="show_hw_screen_updates" msgid="2021286231267747506">"जीपीयू व्यू के अपडेट दिखाएं"</string> <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"GPU से बनाए गए व्यू, विंडो में फ़्लैश करता है"</string> <string name="show_hw_layers_updates" msgid="5268370750002509767">"हार्डवेयर लेयर अपडेट दिखाएं"</string> @@ -376,7 +376,7 @@ <string name="simulate_color_space" msgid="1206503300335835151">"रंग स्पेस सिम्युलेट करें"</string> <string name="enable_opengl_traces_title" msgid="4638773318659125196">"OpenGL ट्रेस चालू करें"</string> <string name="usb_audio_disable_routing" msgid="3367656923544254975">"यूएसबी ऑडियो रूटिंग बंद करें"</string> - <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"यूएसबी ऑडियो पेरिफ़ेरल पर अपने-आप रूटिंग बंद करें"</string> + <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"यूएसबी ऑडियो पेरिफ़ेरल पर अपने-आप रूटिंग होना बंद करें"</string> <string name="debug_layout" msgid="1659216803043339741">"लेआउट सीमाएं दिखाएं"</string> <string name="debug_layout_summary" msgid="8825829038287321978">"क्लिप सीमाएं, मार्जिन वगैरह दिखाएं."</string> <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"लेआउट की दिशा दाएं से बाएं करें"</string> @@ -389,7 +389,7 @@ <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"जीपीयू डीबग लेयर चालू करें"</string> <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"डीबग ऐप के लिए जीपीयू डीबग लेयर लोड करने दें"</string> <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"वर्बोस वेंडर लॉगिंग चालू करें"</string> - <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"गड़बड़ियों की रिपोर्ट में खास डिवाइस से जुड़े वेंडर लॉग शामिल करें. इन लॉग में निजी जानकारी, बैटरी का ज़्यादा इस्तेमाल, और/या डिवाइस की मेमोरी ज़्यादा इस्तेमाल करने की जानकारी हो सकती है."</string> + <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"गड़बड़ियों की रिपोर्ट में खास डिवाइस से जुड़े वेंडर लॉग शामिल करें. इन लॉग में निजी जानकारी, बैटरी का ज़्यादा इस्तेमाल, और/या डिवाइस का स्टोरेज ज़्यादा इस्तेमाल करने की जानकारी हो सकती है."</string> <string name="window_animation_scale_title" msgid="5236381298376812508">"विंडो एनिमेशन स्केल"</string> <string name="transition_animation_scale_title" msgid="1278477690695439337">"ट्रांज़िशन एनिमेशन स्केल"</string> <string name="animator_duration_scale_title" msgid="7082913931326085176">"एनिमेटर अवधि स्केल"</string> @@ -401,11 +401,11 @@ <string name="show_all_anrs" msgid="9160563836616468726">"बैकग्राउंड के ANRs दिखाएं"</string> <string name="show_all_anrs_summary" msgid="8562788834431971392">"बैकग्राउंड में चलने वाले ऐप्लिकेशन के लिए, \'यह ऐप्लिकेशन नहीं चल रहा\' मैसेज दिखाएं"</string> <string name="show_notification_channel_warnings" msgid="3448282400127597331">"सूचना चैनल चेतावनी दिखाएं"</string> - <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"ऐप्लिकेशन, मान्य चैनल के बिना सूचना पोस्ट करे तो स्क्रीन पर चेतावनी दिखाएं"</string> - <string name="force_allow_on_external" msgid="9187902444231637880">"ऐप्लिकेशन को बाहरी मेमोरी पर ही चलाएं"</string> - <string name="force_allow_on_external_summary" msgid="8525425782530728238">"इससे कोई भी ऐप्लिकेशन बाहरी मेमोरी में रखने लायक बन जाता है चाहे उसकी मेनिफ़ेस्ट वैल्यू कुछ भी हो"</string> - <string name="force_resizable_activities" msgid="7143612144399959606">"विंडो के हिसाब से गतिविधियों का आकार बदल दें"</string> - <string name="force_resizable_activities_summary" msgid="2490382056981583062">"सभी गतिविधियों को मल्टी-विंडो (एक से ज़्यादा ऐप्लिकेशन, एक साथ) के लिए आकार बदलने लायक बनाएं, चाहे उनकी मेनिफ़ेस्ट वैल्यू कुछ भी हो."</string> + <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"कोई ऐप, मान्य चैनल के बिना सूचना पोस्ट करे, तो स्क्रीन पर चेतावनी दिखाएं"</string> + <string name="force_allow_on_external" msgid="9187902444231637880">"ऐप्लिकेशन को बाहरी स्टोरेज पर ही चलाएं"</string> + <string name="force_allow_on_external_summary" msgid="8525425782530728238">"इससे कोई भी ऐप्लिकेशन बाहरी स्टोरेज में रखने लायक बन जाता है, चाहे उसकी मेनिफ़ेस्ट वैल्यू कुछ भी हो"</string> + <string name="force_resizable_activities" msgid="7143612144399959606">"विंडो के हिसाब से गतिविधियों का साइज़ बदल दें"</string> + <string name="force_resizable_activities_summary" msgid="2490382056981583062">"सभी गतिविधियों को मल्टी-विंडो (एक से ज़्यादा ऐप्लिकेशन, एक साथ) के लिए साइज़ बदलने लायक बनाएं, चाहे उनकी मेनिफ़ेस्ट वैल्यू कुछ भी हो."</string> <string name="enable_freeform_support" msgid="7599125687603914253">"फ़्रीफ़ॉर्म विंडो (एक साथ कई विंडो दिखाना) चालू करें"</string> <string name="enable_freeform_support_summary" msgid="1822862728719276331">"जांच के लिए बनी फ़्रीफ़ॉर्म विंडो के लिए सहायता चालू करें."</string> <string name="local_backup_password_title" msgid="4631017948933578709">"डेस्कटॉप बैक अप पासवर्ड"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"क्यूआर कोड को स्कैन करें"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"सुनने के लिए, दिए गए क्यूआर कोड को बीच में लाएं"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"क्यूआर कोड का फ़ॉर्मैट गलत है"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> पर ब्रॉडकास्ट करना रोकें?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> पर ब्रॉडकास्ट शुरू करने पर या आउटपुट बदलने पर, आपका मौजूदा ब्रॉडकास्ट बंद हो जाएगा"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> पर ब्रॉडकास्ट करें"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"आउटपुट बदलें"</string> </resources> diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml index 369406fd94d6..fdf14b3fab88 100644 --- a/packages/SettingsLib/res/values-hr/strings.xml +++ b/packages/SettingsLib/res/values-hr/strings.xml @@ -389,7 +389,7 @@ <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Omogući slojeve za otklanjanje pogrešaka GPU-a"</string> <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Omogućite učitavanje slojeva za otklanjanje pogrešaka GPU-a za aplikacije za otklanjanje pogrešaka"</string> <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Omogući opširni zapisnik"</string> - <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Uključite dodatne zapisnike dobavljača pojedinog uređaja u izvješća o programskoj pogrešci koja mogu sadržavati privatne podatke, trošiti više baterije i/ili zauzeti više prostora za pohranu."</string> + <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Uključite dodatne zapisnike dobavljača pojedinog uređaja u izvješća o programskim pogreškama koja mogu sadržavati privatne podatke, trošiti više baterije i/ili zauzeti više prostora za pohranu."</string> <string name="window_animation_scale_title" msgid="5236381298376812508">"Brzina animacije prozora"</string> <string name="transition_animation_scale_title" msgid="1278477690695439337">"Brzina animacije prijelaza"</string> <string name="animator_duration_scale_title" msgid="7082913931326085176">"Razmjer duljine animatora"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Skeniraj QR kôd"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Da biste počeli slušati, centrirajte QR kôd u nastavku"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR kôd nije u važećem formatu"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Zaustaviti emitiranje aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Ako emitirate aplikaciju <xliff:g id="SWITCHAPP">%1$s</xliff:g> ili promijenite izlaz, vaše će se trenutačno emitiranje zaustaviti"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Emitiranje aplikacije <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Promjena izlaza"</string> </resources> diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml index e4bc19126baf..862078055372 100644 --- a/packages/SettingsLib/res/values-hu/strings.xml +++ b/packages/SettingsLib/res/values-hu/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR-kód beolvasása"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"A hallgatás megkezdéséhez igazítsa a QR-kódot az alábbi panel közepére"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"A QR-kód formátuma nem érvényes"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Leállítja a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> közvetítését?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"A(z) <xliff:g id="SWITCHAPP">%1$s</xliff:g> közvetítése vagy a kimenet módosítása esetén a jelenlegi közvetítés leáll"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> közvetítése"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Kimenet módosítása"</string> </resources> diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml index 79a657b2e483..2cd935205664 100644 --- a/packages/SettingsLib/res/values-hy/strings.xml +++ b/packages/SettingsLib/res/values-hy/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR կոդի սկանավորում"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Լսելու համար տեսախցիկը պահեք QR կոդի վրա"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR կոդի ձևաչափն անվավեր է"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Կանգնեցնել <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի հեռարձակումը"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Եթե հեռարձակեք <xliff:g id="SWITCHAPP">%1$s</xliff:g> հավելվածը կամ փոխեք աուդիո ելքը, ձեր ընթացիկ հեռարձակումը կկանգնեցվի։"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Հեռարձակել <xliff:g id="SWITCHAPP">%1$s</xliff:g> հավելվածը"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Փոխել աուդիո ելքը"</string> </resources> diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml index 314b1bb21158..6349e53465ee 100644 --- a/packages/SettingsLib/res/values-in/arrays.xml +++ b/packages/SettingsLib/res/values-in/arrays.xml @@ -55,7 +55,7 @@ </string-array> <string-array name="hdcp_checking_summaries"> <item msgid="4045840870658484038">"Jangan gunakan pemeriksaan HDCP"</item> - <item msgid="8254225038262324761">"Gunakan pemeriksaan HDCP untuk konten DRM saja"</item> + <item msgid="8254225038262324761">"Menggunakan pemeriksaan HDCP untuk konten DRM saja"</item> <item msgid="6421717003037072581">"Selalu gunakan pemeriksaan HDCP"</item> </string-array> <string-array name="bt_hci_snoop_log_entries"> diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index 3bad8e8acfbd..da3c3e634f20 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -264,7 +264,7 @@ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Harap sambungkan ke jaringan Wi-Fi"</string> <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string> <string name="bugreport_in_power" msgid="8664089072534638709">"Pintasan laporan bug"</string> - <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Tampilkan tombol di menu daya untuk mengambil laporan bug"</string> + <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Menampilkan tombol di menu daya untuk mengambil laporan bug"</string> <string name="keep_screen_on" msgid="1187161672348797558">"Tetap terjaga"</string> <string name="keep_screen_on_summary" msgid="1510731514101925829">"Layar tidak akan redup selama mengisi daya"</string> <string name="bt_hci_snoop_log" msgid="7291287955649081448">"Aktifkan log pengintaian HCI Bluetooth"</string> @@ -309,8 +309,8 @@ <string name="private_dns_mode_provider" msgid="3619040641762557028">"Hostname penyedia DNS pribadi"</string> <string name="private_dns_mode_provider_hostname_hint" msgid="6564868953748514595">"Masukkan hostname penyedia DNS"</string> <string name="private_dns_mode_provider_failure" msgid="8356259467861515108">"Tidak dapat terhubung"</string> - <string name="wifi_display_certification_summary" msgid="8111151348106907513">"Tampilkan opsi untuk sertifikasi layar nirkabel"</string> - <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Tingkatkan level pencatatan log Wi-Fi, tampilkan per SSID RSSI di Pemilih Wi‑Fi"</string> + <string name="wifi_display_certification_summary" msgid="8111151348106907513">"Menampilkan opsi untuk sertifikasi tampilan nirkabel"</string> + <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Meningkatkan level pencatatan log Wi-Fi, menampilkan per SSID RSSI di Pemilih Wi‑Fi"</string> <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Memperlambat kehabisan baterai & meningkatkan performa jaringan"</string> <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Jika mode ini diaktifkan, alamat MAC perangkat ini dapat berubah setiap kali terhubung ke jaringan yang mengaktifkan pengacakan MAC."</string> <string name="wifi_metered_label" msgid="8737187690304098638">"Berbayar"</string> @@ -326,8 +326,8 @@ <string name="allow_mock_location" msgid="2102650981552527884">"Mengizinkan lokasi palsu"</string> <string name="allow_mock_location_summary" msgid="179780881081354579">"Mengizinkan lokasi palsu"</string> <string name="debug_view_attributes" msgid="3539609843984208216">"Aktifkan inspeksi atribut tampilan"</string> - <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"Selalu aktifkan kuota, meski Wi-Fi aktif (agar jaringan beralih dengan cepat)."</string> - <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Gunakan akselerasi hardware tethering jika tersedia"</string> + <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"Selalu mengaktifkan data seluler, meskipun Wi-Fi aktif (agar jaringan beralih dengan cepat)."</string> + <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Menggunakan akselerasi hardware tethering jika tersedia"</string> <string name="adb_warning_title" msgid="7708653449506485728">"Izinkan melakukan debug USB?"</string> <string name="adb_warning_message" msgid="8145270656419669221">"Debugging USB dimaksudkan untuk tujuan pengembangan saja. Gunakan untuk menyalin data antara komputer dan perangkat Anda, memasang apl pada perangkat tanpa notifikasi, dan membaca data log."</string> <string name="adbwifi_warning_title" msgid="727104571653031865">"Izinkan proses debug nirkabel?"</string> @@ -336,7 +336,7 @@ <string name="dev_settings_warning_title" msgid="8251234890169074553">"Izinkan setelan pengembangan?"</string> <string name="dev_settings_warning_message" msgid="37741686486073668">"Setelan ini hanya dimaksudkan untuk penggunaan pengembangan. Setelan dapat menyebabkan perangkat dan aplikasi yang menerapkannya rusak atau tidak berfungsi semestinya."</string> <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"Verifikasi aplikasi melalui USB"</string> - <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Periksa perilaku membahayakan dalam aplikasi yang terpasang melalui ADB/ADT."</string> + <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Memeriksa perilaku berbahaya dalam aplikasi yang diinstal melalui ADB/ADT."</string> <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Perangkat Bluetooth tanpa nama (hanya alamat MAC) akan ditampilkan"</string> <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Menonaktifkan fitur volume absolut Bluetooth jika ada masalah volume dengan perangkat jarak jauh, misalnya volume terlalu keras atau kurangnya kontrol."</string> <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Mengaktifkan stack fitur Gabeldorsche Bluetooth."</string> @@ -359,13 +359,13 @@ <string name="media_category" msgid="8122076702526144053">"Media"</string> <string name="debug_monitoring_category" msgid="1597387133765424994">"Memantau"</string> <string name="strict_mode" msgid="889864762140862437">"Mode ketat diaktifkan"</string> - <string name="strict_mode_summary" msgid="1838248687233554654">"Kedipkan layar saat apl beroperasi lama pada utas utama"</string> - <string name="pointer_location" msgid="7516929526199520173">"Lokasi penunjuk"</string> - <string name="pointer_location_summary" msgid="957120116989798464">"Hamparan layar menampilkan data sentuhan saat ini"</string> + <string name="strict_mode_summary" msgid="1838248687233554654">"Mengedipkan layar saat apl berjalan lama di utas utama"</string> + <string name="pointer_location" msgid="7516929526199520173">"Lokasi kursor"</string> + <string name="pointer_location_summary" msgid="957120116989798464">"Overlay layar menampilkan data sentuhan saat ini"</string> <string name="show_touches" msgid="8437666942161289025">"Tampilkan ketukan"</string> - <string name="show_touches_summary" msgid="3692861665994502193">"Tampilkan efek visual untuk ketukan"</string> + <string name="show_touches_summary" msgid="3692861665994502193">"Menampilkan efek visual untuk ketukan"</string> <string name="show_screen_updates" msgid="2078782895825535494">"Lihat pembaruan permukaan"</string> - <string name="show_screen_updates_summary" msgid="2126932969682087406">"Sorot seluruh permukaan jendela saat diperbarui"</string> + <string name="show_screen_updates_summary" msgid="2126932969682087406">"Mengedipkan seluruh permukaan jendela saat diperbarui"</string> <string name="show_hw_screen_updates" msgid="2021286231267747506">"Tampilkan update tampilan"</string> <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"Tampilan cepat dalam jendela saat digambar"</string> <string name="show_hw_layers_updates" msgid="5268370750002509767">"Tunjukkan update lapisan hardware"</string> @@ -375,39 +375,39 @@ <string name="disable_overlays_summary" msgid="1954852414363338166">"Selalu gunakan GPU untuk pengomposisian layar"</string> <string name="simulate_color_space" msgid="1206503300335835151">"Simulasikan ruang warna"</string> <string name="enable_opengl_traces_title" msgid="4638773318659125196">"Aktifkan jejak OpenGL"</string> - <string name="usb_audio_disable_routing" msgid="3367656923544254975">"Pemilihan rute audio USB nonaktif"</string> - <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"Pemilihan rute otomatis ke periferal audio USB nonaktif"</string> + <string name="usb_audio_disable_routing" msgid="3367656923544254975">"Nonaktifkan pemilihan rute audio USB"</string> + <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"Menonaktifkan pemilihan rute otomatis ke periferal audio USB"</string> <string name="debug_layout" msgid="1659216803043339741">"Tampilkan batas tata letak"</string> - <string name="debug_layout_summary" msgid="8825829038287321978">"Tampilkan batas klip, margin, dll."</string> + <string name="debug_layout_summary" msgid="8825829038287321978">"Menampilkan batas klip, margin, dll."</string> <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Paksa arah tata letak RTL"</string> - <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Paksa arah tata letak layar RTL untuk semua lokal"</string> + <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Memaksa arah tata letak layar RTL untuk semua lokalitas"</string> <string name="window_blurs" msgid="6831008984828425106">"Izinkan buram level jendela"</string> <string name="force_msaa" msgid="4081288296137775550">"Paksa 4x MSAA"</string> - <string name="force_msaa_summary" msgid="9070437493586769500">"Aktifkan 4x MSAA dalam aplikasi OpenGL ES 2.0"</string> + <string name="force_msaa_summary" msgid="9070437493586769500">"Mengaktifkan 4x MSAA dalam aplikasi OpenGL ES 2.0"</string> <string name="show_non_rect_clip" msgid="7499758654867881817">"Debug operasi klip non-kotak"</string> <string name="track_frame_time" msgid="522674651937771106">"Rendering HWUI profil"</string> <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Aktifkan lapisan debug GPU"</string> - <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Izinkan memuat lapisan debug GPU untuk aplikasi debug"</string> + <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Mengizinkan lapisan debug GPU dimuat di apl debug"</string> <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Aktifkan logging vendor panjang"</string> - <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Sertakan log vendor khusus perangkat tambahan dalam laporan bug, yang mungkin berisi informasi pribadi, menggunakan lebih banyak baterai, dan/atau menggunakan lebih banyak ruang penyimpanan."</string> + <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Menyertakan log vendor khusus perangkat tambahan dalam laporan bug, yang mungkin berisi informasi pribadi, menggunakan lebih banyak baterai, dan/atau menggunakan lebih banyak ruang penyimpanan."</string> <string name="window_animation_scale_title" msgid="5236381298376812508">"Skala animasi jendela"</string> <string name="transition_animation_scale_title" msgid="1278477690695439337">"Skala animasi transisi"</string> <string name="animator_duration_scale_title" msgid="7082913931326085176">"Skala durasi animator"</string> <string name="overlay_display_devices_title" msgid="5411894622334469607">"Simulasikan tampilan sekunder"</string> <string name="debug_applications_category" msgid="5394089406638954196">"Aplikasi"</string> <string name="immediately_destroy_activities" msgid="1826287490705167403">"Jangan simpan aktivitas"</string> - <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"Hancurkan tiap aktivitas setelah ditinggal pengguna"</string> + <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"Menghancurkan aktivitas setelah apl ditutup"</string> <string name="app_process_limit_title" msgid="8361367869453043007">"Batas proses latar blkng"</string> <string name="show_all_anrs" msgid="9160563836616468726">"Tampilkan ANR latar blkng"</string> - <string name="show_all_anrs_summary" msgid="8562788834431971392">"Tampilkan dialog Aplikasi Tidak Merespons untuk aplikasi yang ada di latar belakang"</string> + <string name="show_all_anrs_summary" msgid="8562788834431971392">"Menampilkan dialog Aplikasi Tidak Merespons untuk aplikasi yang ada di latar belakang"</string> <string name="show_notification_channel_warnings" msgid="3448282400127597331">"Tampilkan peringatan saluran notifikasi"</string> <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"Menampilkan peringatan di layar saat aplikasi memposting notifikasi tanpa channel yang valid"</string> <string name="force_allow_on_external" msgid="9187902444231637880">"Paksa izinkan aplikasi di eksternal"</string> <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Membuat semua aplikasi dapat ditulis ke penyimpanan eksternal, terlepas dari nilai manifes"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Paksa aktivitas agar ukurannya dapat diubah"</string> - <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Buat semua aktivitas dapat diubah ukurannya untuk banyak jendela, terlepas dari nilai manifes."</string> + <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Membuat semua aktivitas dapat diubah ukurannya untuk banyak jendela, terlepas dari nilai manifes."</string> <string name="enable_freeform_support" msgid="7599125687603914253">"Aktifkan jendela berformat bebas"</string> - <string name="enable_freeform_support_summary" msgid="1822862728719276331">"Aktifkan dukungan untuk jendela eksperimental berformat bebas."</string> + <string name="enable_freeform_support_summary" msgid="1822862728719276331">"Mengaktifkan dukungan untuk jendela eksperimental berformat bebas."</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Sandi cadangan desktop"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Saat ini cadangan desktop penuh tidak dilindungi"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Ketuk guna mengubah atau menghapus sandi untuk cadangan lengkap desktop"</string> @@ -448,7 +448,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (merah-hijau)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (biru-kuning)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Koreksi warna"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Koreksi warna dapat berguna jika Anda ingin:<br/> <ol> <li>&nbsp;Melihat warna dengan lebih akurat</li> <li>&nbsp;Menghapus warna untuk membantu Anda fokus</li> </ol>"</string> + <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> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Sekitar <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi"</string> @@ -653,14 +653,10 @@ <string name="allow_turn_screen_on" msgid="6194845766392742639">"Izinkan pengaktifan layar"</string> <string name="allow_turn_screen_on_description" msgid="43834403291575164">"Mengizinkan aplikasi mengaktifkan layar. Jika diizinkan, aplikasi dapat mengaktifkan layar kapan saja tanpa izin Anda."</string> <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Pindai kode QR"</string> - <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Untuk mulai mendengarkan, fokuskan kode QR berikut"</string> + <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Untuk mulai mendengarkan, pusatkan kode QR"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"Format kode QR tidak valid"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Hentikan siaran <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Jika Anda menyiarkan <xliff:g id="SWITCHAPP">%1$s</xliff:g> atau mengubah output, siaran saat ini akan dihentikan"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Siarkan <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Ubah output"</string> </resources> diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml index 9616618da3cb..e0ca6e35c985 100644 --- a/packages/SettingsLib/res/values-is/strings.xml +++ b/packages/SettingsLib/res/values-is/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Skanna QR-kóða"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Byrjaðu að hlusta með því að skanna QR-kóðann hér að neðan"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR-kóði er ekki gilt snið"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Hætta að senda út <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Ef þú sendir út <xliff:g id="SWITCHAPP">%1$s</xliff:g> eða skiptir um úttak lýkur yfirstandandi útsendingu"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Senda út <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Skipta um úttak"</string> </resources> diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml index c80e290870bb..66c7273ab5d3 100644 --- a/packages/SettingsLib/res/values-it/strings.xml +++ b/packages/SettingsLib/res/values-it/strings.xml @@ -312,7 +312,7 @@ <string name="wifi_display_certification_summary" msgid="8111151348106907513">"Mostra opzioni per la certificazione display wireless"</string> <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Aumenta livello di logging Wi-Fi, mostra SSID RSSI nel selettore Wi-Fi"</string> <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Riduce il consumo della batteria e migliora le prestazioni della rete"</string> - <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Quando questa modalità è attiva, l\'indirizzo MAC del dispositivo potrebbe cambiare ogni volta che il dispositivo si connette a una rete con randomizzazione degli indirizzi MAC attiva."</string> + <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Quando questa modalità è attiva, l\'indirizzo MAC del dispositivo potrebbe cambiare ogni volta che il dispositivo si connette a una rete con randomizzazione degli indirizzi MAC attiva"</string> <string name="wifi_metered_label" msgid="8737187690304098638">"A consumo"</string> <string name="wifi_unmetered_label" msgid="6174142840934095093">"Non a consumo"</string> <string name="select_logd_size_title" msgid="1604578195914595173">"Dimensioni buffer logger"</string> @@ -359,17 +359,17 @@ <string name="media_category" msgid="8122076702526144053">"Contenuti multimediali"</string> <string name="debug_monitoring_category" msgid="1597387133765424994">"Monitoraggio"</string> <string name="strict_mode" msgid="889864762140862437">"Attiva StrictMode"</string> - <string name="strict_mode_summary" msgid="1838248687233554654">"Schermo lampeggia per operazioni lunghe su thread principale"</string> + <string name="strict_mode_summary" msgid="1838248687233554654">"Fai lampeggiare lo schermo per operazioni lunghe sul thread principale"</string> <string name="pointer_location" msgid="7516929526199520173">"Posizione puntatore"</string> <string name="pointer_location_summary" msgid="957120116989798464">"Overlay schermo che mostra i dati touch correnti"</string> <string name="show_touches" msgid="8437666942161289025">"Mostra tocchi"</string> <string name="show_touches_summary" msgid="3692861665994502193">"Mostra feedback visivi per i tocchi"</string> <string name="show_screen_updates" msgid="2078782895825535494">"Aggiornamenti superficie"</string> - <string name="show_screen_updates_summary" msgid="2126932969682087406">"Superfici delle finestre lampeggiano se aggiornate"</string> + <string name="show_screen_updates_summary" msgid="2126932969682087406">"Fai lampeggiare le superfici delle finestre quando si aggiornano"</string> <string name="show_hw_screen_updates" msgid="2021286231267747506">"Aggiornam. visualizzazione"</string> - <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"Visualizz. lampeggiano dentro finestre se disegnate"</string> + <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"Fai lampeggiare gli elementi nelle finestre se disegnati"</string> <string name="show_hw_layers_updates" msgid="5268370750002509767">"Aggiornam. livelli hardware"</string> - <string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"Livelli hardware lampeggiano in verde se aggiornati"</string> + <string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"Fai lampeggiare in verde i livelli hardware se aggiornati"</string> <string name="debug_hw_overdraw" msgid="8944851091008756796">"Debug overdraw GPU"</string> <string name="disable_overlays" msgid="4206590799671557143">"Disabilita overlay HW"</string> <string name="disable_overlays_summary" msgid="1954852414363338166">"Usa sempre GPU per la composizione dello schermo"</string> @@ -405,9 +405,9 @@ <string name="force_allow_on_external" msgid="9187902444231637880">"Forza autorizzazione app su memoria esterna"</string> <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Consente l\'installazione di qualsiasi app su memoria esterna, indipendentemente dai valori manifest"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Imponi formato modificabile alle attività"</string> - <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Rendi il formato di tutte le attività modificabile per la modalità multi-finestra, indipendentemente dai valori manifest."</string> + <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Rendi il formato di tutte le attività modificabile per la modalità multi-finestra, indipendentemente dai valori manifest"</string> <string name="enable_freeform_support" msgid="7599125687603914253">"Attiva finestre a forma libera"</string> - <string name="enable_freeform_support_summary" msgid="1822862728719276331">"Attiva il supporto delle finestre a forma libera sperimentali."</string> + <string name="enable_freeform_support_summary" msgid="1822862728719276331">"Attiva il supporto delle finestre a forma libera sperimentali"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Password di backup desktop"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"I backup desktop completi non sono attualmente protetti"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"Tocca per modificare o rimuovere la password per i backup desktop completi"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Scansiona codice QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Per iniziare ad ascoltare, centra il codice QR qui sotto"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"Il formato del codice QR non è valido"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Vuoi interrompere la trasmissione dell\'app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Se trasmetti l\'app <xliff:g id="SWITCHAPP">%1$s</xliff:g> o cambi l\'uscita, la trasmissione attuale viene interrotta"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Trasmetti l\'app <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Cambia uscita"</string> </resources> diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml index 4304abdfffc5..2196c75ddde6 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -568,9 +568,9 @@ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"ניתן להגביל את הגישה לאפליקציות ולתוכן מהחשבון שלך"</string> <string name="user_add_user_item_title" msgid="2394272381086965029">"משתמש"</string> <string name="user_add_profile_item_title" msgid="3111051717414643029">"פרופיל מוגבל"</string> - <string name="user_add_user_title" msgid="5457079143694924885">"האם להוסיף משתמש חדש?"</string> + <string name="user_add_user_title" msgid="5457079143694924885">"להוסיף משתמש חדש?"</string> <string name="user_add_user_message_long" msgid="1527434966294733380">"ניתן לשתף מכשיר זה עם אנשים אחרים על ידי יצירת משתמשים נוספים. לכל משתמש מרחב משלו, שאותו אפשר להתאים אישית בעזרת אפליקציות, טפט ופריטים נוספים. המשתמשים יכולים גם להתאים הגדרות של המכשיר כגון Wi‑Fi, שמשפיעות על כולם.\n\nכשמוסיפים משתמש חדש, על משתמש זה להגדיר את המרחב שלו.\n\nכל אחד מהמשתמשים יכול לעדכן אפליקציות לכל שאר המשתמשים. ייתכן שהגדרות ושירותים של נגישות לא יועברו למשתמש החדש."</string> - <string name="user_add_user_message_short" msgid="3295959985795716166">"בעת הוספת משתמש חדש, על משתמש זה להגדיר את השטח שלו.\n\nכל משתמש יכול לעדכן אפליקציות עבור כל המשתמשים האחרים."</string> + <string name="user_add_user_message_short" msgid="3295959985795716166">"כשמוסיפים משתמש חדש, המשתמש הזה צריך להגדיר את המרחב שלו.\n\nכל משתמש יכול לעדכן אפליקציות עבור כל המשתמשים האחרים."</string> <string name="user_setup_dialog_title" msgid="8037342066381939995">"האם להגדיר משתמש עכשיו?"</string> <string name="user_setup_dialog_message" msgid="269931619868102841">"כדאי לוודא שהמשתמש זמין ויכול לקחת את המכשיר ולהגדיר את המרחב שלו"</string> <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"האם להגדיר פרופיל עכשיו?"</string> @@ -591,7 +591,7 @@ <string name="user_nickname" msgid="262624187455825083">"כינוי"</string> <string name="user_add_user" msgid="7876449291500212468">"הוספת משתמש"</string> <string name="guest_new_guest" msgid="3482026122932643557">"הוספת אורח"</string> - <string name="guest_exit_guest" msgid="5908239569510734136">"הסרת אורח/ת"</string> + <string name="guest_exit_guest" msgid="5908239569510734136">"הסרת אורח"</string> <string name="guest_reset_guest" msgid="6110013010356013758">"איפוס הגלישה כאורח"</string> <string name="guest_reset_guest_dialog_title" msgid="8047270010895437534">"לאפס את הגלישה כאורח?"</string> <string name="guest_remove_guest_dialog_title" msgid="4548511006624088072">"להסיר את האורח/ת?"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"סריקת קוד QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"כדי להתחיל בהאזנה, צריך להציב את קוד ה‑QR במרכז החלון שבהמשך"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"הפורמט של קוד ה‑QR לא תקין"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"האם להפסיק לשדר את התוכן מאפליקציית <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"אם משדרים את התוכן מאפליקציית <xliff:g id="SWITCHAPP">%1$s</xliff:g> או משנים את הפלט, השידור הנוכחי יפסיק לפעול"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"שידור תוכן מאפליקציית <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"שינוי הפלט"</string> </resources> diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml index 110e72b91b85..ad84d9ed6fba 100644 --- a/packages/SettingsLib/res/values-ja/arrays.xml +++ b/packages/SettingsLib/res/values-ja/arrays.xml @@ -191,30 +191,30 @@ </string-array> <string-array name="window_animation_scale_entries"> <item msgid="2675263395797191850">"アニメーションオフ"</item> - <item msgid="5790132543372767872">"アニメーションスケール.5x"</item> - <item msgid="2529692189302148746">"アニメーションスケール1x"</item> - <item msgid="8072785072237082286">"アニメーションスケール1.5x"</item> - <item msgid="3531560925718232560">"アニメーションスケール2x"</item> - <item msgid="4542853094898215187">"アニメーションスケール5x"</item> - <item msgid="5643881346223901195">"アニメーションスケール10x"</item> + <item msgid="5790132543372767872">"アニメーション スケール .5x"</item> + <item msgid="2529692189302148746">"アニメーション スケール 1x"</item> + <item msgid="8072785072237082286">"アニメーション スケール 1.5x"</item> + <item msgid="3531560925718232560">"アニメーション スケール 2x"</item> + <item msgid="4542853094898215187">"アニメーション スケール 5x"</item> + <item msgid="5643881346223901195">"アニメーション スケール 10x"</item> </string-array> <string-array name="transition_animation_scale_entries"> <item msgid="3376676813923486384">"アニメーションオフ"</item> - <item msgid="753422683600269114">"アニメーションスケール.5x"</item> - <item msgid="3695427132155563489">"アニメーションスケール1x"</item> - <item msgid="9032615844198098981">"アニメーションスケール1.5x"</item> - <item msgid="8473868962499332073">"アニメーションスケール2x"</item> - <item msgid="4403482320438668316">"アニメーションスケール5x"</item> - <item msgid="169579387974966641">"アニメーションスケール10x"</item> + <item msgid="753422683600269114">"アニメーション スケール .5x"</item> + <item msgid="3695427132155563489">"アニメーション スケール 1x"</item> + <item msgid="9032615844198098981">"アニメーション スケール 1.5x"</item> + <item msgid="8473868962499332073">"アニメーション スケール 2x"</item> + <item msgid="4403482320438668316">"アニメーション スケール 5x"</item> + <item msgid="169579387974966641">"アニメーション スケール 10x"</item> </string-array> <string-array name="animator_duration_scale_entries"> <item msgid="6416998593844817378">"アニメーションオフ"</item> - <item msgid="875345630014338616">"アニメーションスケール.5x"</item> - <item msgid="2753729231187104962">"アニメーションスケール1x"</item> - <item msgid="1368370459723665338">"アニメーションスケール1.5x"</item> - <item msgid="5768005350534383389">"アニメーションスケール2x"</item> - <item msgid="3728265127284005444">"アニメーションスケール5x"</item> - <item msgid="2464080977843960236">"アニメーションスケール10x"</item> + <item msgid="875345630014338616">"アニメーション スケール .5x"</item> + <item msgid="2753729231187104962">"アニメーション スケール 1x"</item> + <item msgid="1368370459723665338">"アニメーション スケール 1.5x"</item> + <item msgid="5768005350534383389">"アニメーション スケール 2x"</item> + <item msgid="3728265127284005444">"アニメーション スケール 5x"</item> + <item msgid="2464080977843960236">"アニメーション スケール 10x"</item> </string-array> <string-array name="overlay_display_devices_entries"> <item msgid="4497393944195787240">"なし"</item> diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml index 770f94446d4f..ae428df2a285 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -236,7 +236,7 @@ <string name="enable_adb_summary" msgid="3711526030096574316">"USB 接続時はデバッグモードにする"</string> <string name="clear_adb_keys" msgid="3010148733140369917">"USB デバッグの許可の取り消し"</string> <string name="enable_adb_wireless" msgid="6973226350963971018">"ワイヤレス デバッグ"</string> - <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi-Fi 接続時にデバッグモード"</string> + <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi-Fi 接続時はデバッグモードにする"</string> <string name="adb_wireless_error" msgid="721958772149779856">"エラー"</string> <string name="adb_wireless_settings" msgid="2295017847215680229">"ワイヤレス デバッグ"</string> <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"利用可能なデバイスを確認して使用するには、ワイヤレス デバッグを ON にしてください"</string> @@ -264,7 +264,7 @@ <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Wi-Fi ネットワークに接続してください"</string> <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, デバッグ, dev"</string> <string name="bugreport_in_power" msgid="8664089072534638709">"バグレポートのショートカット"</string> - <string name="bugreport_in_power_summary" msgid="1885529649381831775">"電源ボタン メニューにバグレポートを取得するボタンを表示する"</string> + <string name="bugreport_in_power_summary" msgid="1885529649381831775">"電源ボタンメニューにバグレポートを取得するボタンを表示する"</string> <string name="keep_screen_on" msgid="1187161672348797558">"スリープモードにしない"</string> <string name="keep_screen_on_summary" msgid="1510731514101925829">"充電中に画面をスリープにしない"</string> <string name="bt_hci_snoop_log" msgid="7291287955649081448">"Bluetooth HCI スヌープログ"</string> @@ -336,7 +336,7 @@ <string name="dev_settings_warning_title" msgid="8251234890169074553">"開発用の設定を許可しますか?"</string> <string name="dev_settings_warning_message" msgid="37741686486073668">"これらの設定は開発専用に設計されています。そのためデバイスやデバイス上のアプリが故障したり正常に動作しなくなったりするおそれがあります。"</string> <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"USB 経由のアプリも検証"</string> - <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT経由でインストールされたアプリに不正な動作がないかを確認する"</string> + <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT 経由でインストールされたアプリに不正な動作がないかを確認する"</string> <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Bluetooth デバイスを名前なしで(MAC アドレスのみで)表示します"</string> <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"リモートデバイスで音量に関する問題(音量が大きすぎる、制御できないなど)が発生した場合に、Bluetooth の絶対音量の機能を無効にする"</string> <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Bluetooth Gabeldorsche 機能スタックを有効にします。"</string> @@ -364,23 +364,23 @@ <string name="pointer_location_summary" msgid="957120116989798464">"現在のタップデータをオーバーレイ表示する"</string> <string name="show_touches" msgid="8437666942161289025">"タップを表示"</string> <string name="show_touches_summary" msgid="3692861665994502193">"タップを視覚表示する"</string> - <string name="show_screen_updates" msgid="2078782895825535494">"表示面の更新を表示"</string> + <string name="show_screen_updates" msgid="2078782895825535494">"表示面の更新を通知"</string> <string name="show_screen_updates_summary" msgid="2126932969682087406">"更新時にウィンドウの表示面全体を点滅させる"</string> <string name="show_hw_screen_updates" msgid="2021286231267747506">"画面の更新を表示"</string> <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">"HW オーバーレイを無効化"</string> <string name="disable_overlays_summary" msgid="1954852414363338166">"画面合成に常に GPU を使用する"</string> <string name="simulate_color_space" msgid="1206503300335835151">"色空間シミュレート"</string> <string name="enable_opengl_traces_title" msgid="4638773318659125196">"OpenGLトレースを有効化"</string> - <string name="usb_audio_disable_routing" msgid="3367656923544254975">"USBオーディオルーティングを無効化"</string> - <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"USBオーディオ周辺機器への自動ルーティングを無効化"</string> + <string name="usb_audio_disable_routing" msgid="3367656923544254975">"USB オーディオ ルーティングを無効化"</string> + <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"USB オーディオ周辺機器への自動ルーティングを無効にする"</string> <string name="debug_layout" msgid="1659216803043339741">"レイアウト境界を表示"</string> <string name="debug_layout_summary" msgid="8825829038287321978">"クリップの境界線、マージンなどを表示"</string> - <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTLレイアウト方向を使用"</string> - <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"すべての言語/地域で画面レイアウト方向をRTLに設定"</string> + <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL レイアウト方向を使用"</string> + <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"すべての言語/地域で画面レイアウト方向を RTL に設定"</string> <string name="window_blurs" msgid="6831008984828425106">"ウィンドウ レベルでのぼかしを許可"</string> <string name="force_msaa" msgid="4081288296137775550">"4x MSAA を適用"</string> <string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 アプリで 4x MSAA を有効にする"</string> @@ -390,18 +390,18 @@ <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"デバッグアプリに GPU デバッグレイヤの読み込みを許可"</string> <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"ベンダーの詳細なロギングを有効にする"</string> <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"バグレポートには、その他のデバイス固有のベンダーログが含まれます。これには、非公開の情報が含まれることがあります。また、バッテリーやストレージの使用量が増えることもあります。"</string> - <string name="window_animation_scale_title" msgid="5236381298376812508">"ウィンドウアニメスケール"</string> - <string name="transition_animation_scale_title" msgid="1278477690695439337">"トランジションアニメスケール"</string> - <string name="animator_duration_scale_title" msgid="7082913931326085176">"Animator再生時間スケール"</string> - <string name="overlay_display_devices_title" msgid="5411894622334469607">"2次画面シミュレート"</string> + <string name="window_animation_scale_title" msgid="5236381298376812508">"ウィンドウ アニメ スケール"</string> + <string name="transition_animation_scale_title" msgid="1278477690695439337">"トランジション アニメ スケール"</string> + <string name="animator_duration_scale_title" msgid="7082913931326085176">"Animator 再生時間スケール"</string> + <string name="overlay_display_devices_title" msgid="5411894622334469607">"2 次画面シミュレート"</string> <string name="debug_applications_category" msgid="5394089406638954196">"アプリ"</string> <string name="immediately_destroy_activities" msgid="1826287490705167403">"アクティビティを保持しない"</string> - <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"ユーザーが離れたアクティビティをただちに破棄します"</string> + <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"ユーザーが離れたアクティビティを直ちに破棄する"</string> <string name="app_process_limit_title" msgid="8361367869453043007">"バックグラウンドプロセスの上限"</string> <string name="show_all_anrs" msgid="9160563836616468726">"バックグラウンド ANR の表示"</string> - <string name="show_all_anrs_summary" msgid="8562788834431971392">"バックグラウンド アプリが応答しない場合にダイアログを表示"</string> + <string name="show_all_anrs_summary" msgid="8562788834431971392">"バックグラウンド アプリが応答しない場合にダイアログを表示する"</string> <string name="show_notification_channel_warnings" msgid="3448282400127597331">"通知チャネルの警告を表示"</string> - <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"アプリから有効なチャネルのない通知が投稿されたときに画面上に警告を表示します"</string> + <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"アプリから有効なチャネルのない通知が投稿されたときに、画面上に警告を表示する"</string> <string name="force_allow_on_external" msgid="9187902444231637880">"外部ストレージへのアプリの書き込みを許可"</string> <string name="force_allow_on_external_summary" msgid="8525425782530728238">"マニフェストの値に関係なく、すべてのアプリを外部ストレージに書き込めるようになります"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"アクティビティをサイズ変更可能にする"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR コードをスキャン"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"再生を開始するには、下の枠に QR コードを合わせてください"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR コードの形式が無効です"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> のブロードキャストを停止しますか?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> をブロードキャストしたり、出力を変更したりすると、現在のブロードキャストが停止します。"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> をブロードキャスト"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"出力を変更"</string> </resources> diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml index 66a05f19474f..c6a50ac9e565 100644 --- a/packages/SettingsLib/res/values-ka/strings.xml +++ b/packages/SettingsLib/res/values-ka/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR კოდის სკანირება"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"მოსმენის დასაწყებად ცენტრში მოაქციეთ ქვემოთ მოცემული QR კოდი"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR კოდის ფორმატი არასწორია"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"გსურთ <xliff:g id="APP_NAME">%1$s</xliff:g>-ის ტრანსლაციის შეჩერება?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"<xliff:g id="SWITCHAPP">%1$s</xliff:g>-ის ტრანსლაციის შემთხვევაში ან აუდიოს გამოსასვლელის შეცვლისას, მიმდინარე ტრანსლაცია შეჩერდება"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g>-ის ტრანსლაცია"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"აუდიოს გამოსასვლელის შეცვლა"</string> </resources> diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml index bbfa2a3e1513..f5559d270f0a 100644 --- a/packages/SettingsLib/res/values-kk/strings.xml +++ b/packages/SettingsLib/res/values-kk/strings.xml @@ -175,7 +175,7 @@ <string name="data_usage_ota" msgid="7984667793701597001">"Жүйелік жаңарту"</string> <string name="tether_settings_title_usb" msgid="3728686573430917722">"USB тетеринг"</string> <string name="tether_settings_title_wifi" msgid="4803402057533895526">"Алынбалы хот-спот"</string> - <string name="tether_settings_title_bluetooth" msgid="916519902721399656">"Bluetooth модем"</string> + <string name="tether_settings_title_bluetooth" msgid="916519902721399656">"Bluetooth тетеринг"</string> <string name="tether_settings_title_usb_bluetooth" msgid="1727111807207577322">"Тетеринг"</string> <string name="tether_settings_title_all" msgid="8910259483383010470">"Тетеринг және алынбалы хотспот"</string> <string name="managed_user_title" msgid="449081789742645723">"Барлық жұмыс қолданбалары"</string> @@ -327,7 +327,7 @@ <string name="allow_mock_location_summary" msgid="179780881081354579">"Жасанды аймақтарды пайдалануға рұқсат беру"</string> <string name="debug_view_attributes" msgid="3539609843984208216">"Көру төлсипатын тексеруді қосу"</string> <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"Wi‑Fi қосулы кезде де мобильдік интернетті өшірмеу (желіні жылдам ауыстыру үшін)"</string> - <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Тетеринг режиміндегі аппараттық жеделдетуді пайдалану (қолжетімді болса)"</string> + <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Тетеринг режимінде аппаратпен жеделдетуді пайдалану (қолжетімді болса)"</string> <string name="adb_warning_title" msgid="7708653449506485728">"USB арқылы түзетуге рұқсат берілсін бе?"</string> <string name="adb_warning_message" msgid="8145270656419669221">"USB арқылы түзету дамыту мақсаттарына ғана арналған. Оны компьютер және құрылғы арасында дерек көшіру, құрылғыға ескертусіз қолданба орнату және журнал деректерін оқу үшін қолданыңыз."</string> <string name="adbwifi_warning_title" msgid="727104571653031865">"Сымсыз түзетуге рұқсат берілсін бе?"</string> @@ -352,7 +352,7 @@ <string name="select_application" msgid="2543228890535466325">"Қолданба таңдау"</string> <string name="no_application" msgid="9038334538870247690">"Ешнәрсе"</string> <string name="wait_for_debugger" msgid="7461199843335409809">"Түзеткішті күту"</string> - <string name="wait_for_debugger_summary" msgid="6846330006113363286">"Орындау алдында түзелетін қолданба түзетушінің қосылуын күтеді"</string> + <string name="wait_for_debugger_summary" msgid="6846330006113363286">"Орындау алдында түзелетін қолданба түзетушінің қосылуын күтеді."</string> <string name="debug_input_category" msgid="7349460906970849771">"Енгізу"</string> <string name="debug_drawing_category" msgid="5066171112313666619">"Сызу"</string> <string name="debug_hw_drawing_category" msgid="5830815169336975162">"Бейнелеуді аппаратпен жеделдету"</string> @@ -385,7 +385,7 @@ <string name="force_msaa" msgid="4081288296137775550">"4x MSAA қолдану"</string> <string name="force_msaa_summary" msgid="9070437493586769500">"4x MSAA функциясын OpenGL ES 2.0 қолданбаларында іске қосу"</string> <string name="show_non_rect_clip" msgid="7499758654867881817">"Тіктөртбұрыштан басқа пішінге қиюды түзету"</string> - <string name="track_frame_time" msgid="522674651937771106">"Профиль бойынша HWUI рендерингі"</string> + <string name="track_frame_time" msgid="522674651937771106">"Профильдегі HWUI рендерингі"</string> <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"GPU түзету қабаттары"</string> <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"GPU түзету қабаттарының жүктелуіне рұқсат ету"</string> <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Жеткізуші туралы толық мәліметті тіркеу"</string> @@ -397,16 +397,16 @@ <string name="debug_applications_category" msgid="5394089406638954196">"Қолданбалар"</string> <string name="immediately_destroy_activities" msgid="1826287490705167403">"Әрекеттерді сақтамау"</string> <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"Әр әрекетті пайдаланушы аяқтай салысымен жою"</string> - <string name="app_process_limit_title" msgid="8361367869453043007">"Фондық үрдіс шектеуі"</string> + <string name="app_process_limit_title" msgid="8361367869453043007">"Фондық процесті шектеу"</string> <string name="show_all_anrs" msgid="9160563836616468726">"Фондық ANR-ларды көрсету"</string> <string name="show_all_anrs_summary" msgid="8562788834431971392">"Фондық қолданбалар үшін \"Қолданба жауап бермейді\" терезесін шығару"</string> <string name="show_notification_channel_warnings" msgid="3448282400127597331">"Хабарландыру арнасының ескертулерін көрсету"</string> <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"Қолданба жарамсыз арна арқылы хабарландыру жариялағанда, экранға ескерту шығарады."</string> - <string name="force_allow_on_external" msgid="9187902444231637880">"Сыртқы жадта қолданбаларға рұқсат ету"</string> + <string name="force_allow_on_external" msgid="9187902444231637880">"Сыртқы жадта сақтауға рұқсат ету"</string> <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Манифест мәндеріне қарамастан, кез келген қолданбаны сыртқы жадқа жазуға рұқсат беру"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Әрекеттердің өлшемін өзгертуге рұқсат ету"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Манифест мәндеріне қарамастан, бірнеше терезе режимінде барлық әрекеттердің өлшемін өзгертуге рұқсат беру"</string> - <string name="enable_freeform_support" msgid="7599125687603914253">"Еркін пішіндегі терезелерді қосу"</string> + <string name="enable_freeform_support" msgid="7599125687603914253">"Еркін пішінді терезелерге рұқсат беру"</string> <string name="enable_freeform_support_summary" msgid="1822862728719276331">"Еркін пішінді терезелерді құру эксперименттік функиясын қосу"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"Компьютердегі сақтық көшірме құпия сөзі"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"Компьютердегі толық сақтық көшірмелер қазір қорғалмаған."</string> @@ -429,7 +429,7 @@ <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Белсенді емес. Ауыстырып қосу үшін түртіңіз."</string> <string name="inactive_app_active_summary" msgid="8047630990208722344">"Белсенді. Ауыстырып қосу үшін түртіңіз."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Қолданбаның күту режимі: <xliff:g id="BUCKET"> %s</xliff:g>"</string> - <string name="transcode_settings_title" msgid="2581975870429850549">"Медиамазмұнды қайта кодтау параметрлері"</string> + <string name="transcode_settings_title" msgid="2581975870429850549">"Медиафайлдарды қайта кодтау параметрлері"</string> <string name="transcode_user_control" msgid="6176368544817731314">"Қайта қодтаудың әдепкі параметрлерін қайта анықтау"</string> <string name="transcode_enable_all" msgid="2411165920039166710">"Қайта кодтауды қосу"</string> <string name="transcode_default" msgid="3784803084573509491">"Қолданбалар қазіргі заманғы форматтарды қолдайды делік"</string> @@ -605,7 +605,7 @@ <string name="failed_attempts_now_wiping_user" msgid="469060411789668050">"Тым көп қате әрекет жасалды. Бұл пайдаланушы жойылады."</string> <string name="failed_attempts_now_wiping_profile" msgid="7626589520888963129">"Тым көп қате әрекет жасалды. Бұл жұмыс профилі мен оның деректері жойылады."</string> <string name="failed_attempts_now_wiping_dialog_dismiss" msgid="2749889771223578925">"Жабу"</string> - <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Құрылғының әдепкі параметрлері"</string> + <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Құрылғының әдепкі параметрі"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Өшірулі"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Қосулы"</string> <string name="cached_apps_freezer_reboot_dialog_text" msgid="695330563489230096">"Бұл өзгеріс күшіне енуі үшін, құрылғыны қайта жүктеу керек. Қазір қайта жүктеңіз не бас тартыңыз."</string> diff --git a/packages/SettingsLib/res/values-km/arrays.xml b/packages/SettingsLib/res/values-km/arrays.xml index 56b98dc59a6e..ef3aa522163a 100644 --- a/packages/SettingsLib/res/values-km/arrays.xml +++ b/packages/SettingsLib/res/values-km/arrays.xml @@ -249,7 +249,7 @@ <string-array name="debug_hw_overdraw_entries"> <item msgid="1968128556747588800">"បិទ"</item> <item msgid="3033215374382962216">"បង្ហាញតំបន់ដែលលើស"</item> - <item msgid="3474333938380896988">"បង្ហាញតំបន់សម្រាប់ Deuteranomaly"</item> + <item msgid="3474333938380896988">"បង្ហាញតំបន់សម្រាប់បញ្ហាខ្វាក់ពណ៌បៃតង"</item> </string-array> <string-array name="app_process_limit_entries"> <item msgid="794656271086646068">"ដែនកំណត់ស្តង់ដារ"</item> diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml index 9085fb6a25b3..a770f61f2acf 100644 --- a/packages/SettingsLib/res/values-km/strings.xml +++ b/packages/SettingsLib/res/values-km/strings.xml @@ -185,9 +185,9 @@ <string name="launch_defaults_none" msgid="8049374306261262709">"គ្មានការកំណត់លំនាំដើម"</string> <string name="tts_settings" msgid="8130616705989351312">"ការកំណត់អត្ថបទទៅជាកានិយាយ"</string> <string name="tts_settings_title" msgid="7602210956640483039">"ធាតុចេញនៃការបំប្លែងអត្ថបទទៅជាការនិយាយ"</string> - <string name="tts_default_rate_title" msgid="3964187817364304022">"អត្រានិយាយ"</string> + <string name="tts_default_rate_title" msgid="3964187817364304022">"ល្បឿននិយាយ"</string> <string name="tts_default_rate_summary" msgid="3781937042151716987">"ល្បឿនពេលអានអត្ថបទ"</string> - <string name="tts_default_pitch_title" msgid="6988592215554485479">"ឡើង-ចុះ"</string> + <string name="tts_default_pitch_title" msgid="6988592215554485479">"សំឡេងទាបខ្ពស់"</string> <string name="tts_default_pitch_summary" msgid="9132719475281551884">"ប៉ះពាល់ដល់សំឡេងនៃការនិយាយដែលបានបម្លែង"</string> <string name="tts_default_lang_title" msgid="4698933575028098940">"ភាសា"</string> <string name="tts_lang_use_system" msgid="6312945299804012406">"ប្រើភាសាប្រព័ន្ធ"</string> @@ -224,7 +224,7 @@ </string-array> <string name="choose_profile" msgid="343803890897657450">"ជ្រើសរើសកម្រងព័ត៌មាន"</string> <string name="category_personal" msgid="6236798763159385225">"ផ្ទាល់ខ្លួន"</string> - <string name="category_work" msgid="4014193632325996115">"កន្លែងធ្វើការ"</string> + <string name="category_work" msgid="4014193632325996115">"ការងារ"</string> <string name="development_settings_title" msgid="140296922921597393">"ជម្រើសសម្រាប់អ្នកអភិវឌ្ឍន៍"</string> <string name="development_settings_enable" msgid="4285094651288242183">"បើកដំណើរការជម្រើសអ្នកអភិវឌ្ឍន៍"</string> <string name="development_settings_summary" msgid="8718917813868735095">"កំណត់ជម្រើសសម្រាប់ការអភិវឌ្ឍកម្មវិធី"</string> @@ -234,7 +234,7 @@ <string name="apn_settings_not_available" msgid="1147111671403342300">"ការកំណត់ឈ្មោះចូលដំណើរការមិនអាចប្រើបានសម្រាប់អ្នកប្រើនេះ"</string> <string name="enable_adb" msgid="8072776357237289039">"ការជួសជុលតាម USB"</string> <string name="enable_adb_summary" msgid="3711526030096574316">"មុខងារជួសជុល នៅពេលភ្ជាប់ USB"</string> - <string name="clear_adb_keys" msgid="3010148733140369917">"ដកសិទ្ធិកែកំហុសតាម USB"</string> + <string name="clear_adb_keys" msgid="3010148733140369917">"ដកសិទ្ធិជួសជុលតាម USB"</string> <string name="enable_adb_wireless" msgid="6973226350963971018">"ការជួសជុលដោយឥតខ្សែ"</string> <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"មុខងារជួសជុល នៅពេលភ្ជាប់ Wi‑Fi"</string> <string name="adb_wireless_error" msgid="721958772149779856">"បញ្ហា"</string> @@ -399,7 +399,7 @@ <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"បំផ្លាញគ្រប់សកម្មភាព ពេលអ្នកប្រើចាកចេញ"</string> <string name="app_process_limit_title" msgid="8361367869453043007">"ដែនកំណត់ដំណើរការក្នុងផ្ទៃខាងក្រោយ"</string> <string name="show_all_anrs" msgid="9160563836616468726">"បង្ហាញ ANR ផ្ទៃខាងក្រោយ"</string> - <string name="show_all_anrs_summary" msgid="8562788834431971392">"បង្ហាញប្រអប់កម្មវិធីមិនឆ្លើយតបសម្រាប់កម្មវិធីផ្ទៃខាងក្រោយ"</string> + <string name="show_all_anrs_summary" msgid="8562788834431971392">"បង្ហាញប្រអប់ \"កម្មវិធីមិនឆ្លើយតប\" សម្រាប់កម្មវិធីផ្ទៃខាងក្រោយ"</string> <string name="show_notification_channel_warnings" msgid="3448282400127597331">"បង្ហាញការព្រមានអំពីបណ្តាញជូនដំណឹង"</string> <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"បង្ហាញការព្រមាននៅលើអេក្រង់ នៅពេលកម្មវិធីបង្ហោះការជូនដំណឹងដោយមិនមានបណ្តាញត្រឹមត្រូវ"</string> <string name="force_allow_on_external" msgid="9187902444231637880">"បង្ខំឲ្យអនុញ្ញាតកម្មវិធីលើឧបករណ៍ផ្ទុកខាងក្រៅ"</string> @@ -407,7 +407,7 @@ <string name="force_resizable_activities" msgid="7143612144399959606">"បង្ខំឲ្យសកម្មភាពអាចប្តូរទំហំបាន"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"ធ្វើឲ្យសកម្មភាពទាំងអស់អាចប្តូរទំហំបានសម្រាប់ពហុវិនដូ ដោយមិនគិតពីតម្លៃមេនីហ្វេសថ៍។"</string> <string name="enable_freeform_support" msgid="7599125687603914253">"បើកដំណើរការផ្ទាំងវិនដូទម្រង់សេរី"</string> - <string name="enable_freeform_support_summary" msgid="1822862728719276331">"បើកដំណើរការគាំទ្រផ្ទាំងវិនដូទម្រង់សេរីសាកល្បង"</string> + <string name="enable_freeform_support_summary" msgid="1822862728719276331">"បើកឱ្យអាចប្រើផ្ទាំងវិនដូទម្រង់សេរីពិសោធន៍។"</string> <string name="local_backup_password_title" msgid="4631017948933578709">"ពាក្យសម្ងាត់បម្រុងទុកលើកុំព្យូទ័រ"</string> <string name="local_backup_password_summary_none" msgid="7646898032616361714">"បច្ចុប្បន្ន ការបម្រុងទុកពេញលេញនៅលើកុំព្យូទ័រមិនត្រូវបានការពារទេ"</string> <string name="local_backup_password_summary_change" msgid="1707357670383995567">"ប៉ះដើម្បីប្ដូរ ឬយកពាក្យសម្ងាត់ចេញសម្រាប់ការបម្រុងទុកពេញលេញលើកុំព្យូទ័រ"</string> @@ -444,10 +444,10 @@ <string name="picture_color_mode_desc" msgid="151780973768136200">"ប្រើ sRGB"</string> <string name="daltonizer_mode_disabled" msgid="403424372812399228">"បានបិទ"</string> <string name="daltonizer_mode_monochromacy" msgid="362060873835885014">"Monochromacy"</string> - <string name="daltonizer_mode_deuteranomaly" msgid="3507284319584683963">"Deuteranomaly (ក្រហមពណ៌បៃតង)"</string> - <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (ក្រហមពណ៌បៃតង)"</string> - <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (ពណ៌ខៀវ-លឿង)"</string> - <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ការកែពណ៌"</string> + <string name="daltonizer_mode_deuteranomaly" msgid="3507284319584683963">"ខ្វាក់ពណ៌បៃតង (ក្រហមបៃតង)"</string> + <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ខ្វាក់ពណ៌ក្រហម (ក្រហមបៃតង)"</string> + <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ខ្វាក់ពណ៌ខៀវ (ខៀវលឿង)"</string> + <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ការកែតម្រូវពណ៌"</string> <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> @@ -490,7 +490,7 @@ <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"គ្រប់គ្រងដោយការកំណត់ដែលបានរឹតបន្តឹង"</string> <string name="disabled" msgid="8017887509554714950">"បិទ"</string> <string name="external_source_trusted" msgid="1146522036773132905">"បានអនុញ្ញាត"</string> - <string name="external_source_untrusted" msgid="5037891688911672227">"មិនអនុញ្ញាតទេ"</string> + <string name="external_source_untrusted" msgid="5037891688911672227">"មិនបានអនុញ្ញាត"</string> <string name="install_other_apps" msgid="3232595082023199454">"ដំឡើងកម្មវិធីដែលមិនស្គាល់"</string> <string name="home" msgid="973834627243661438">"ទំព័រដើមនៃការកំណត់"</string> <string-array name="battery_labels"> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"ស្កេនកូដ QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"ដើម្បីចាប់ផ្ដើមស្ដាប់ សូមដាក់កូដ QR ខាងក្រោមឱ្យនៅចំកណ្ដាល"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"កូដ QR មិនមែនជាទម្រង់ដែលត្រឹមត្រូវទេ"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"បញ្ឈប់ការផ្សាយ <xliff:g id="APP_NAME">%1$s</xliff:g> ឬ?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"ប្រសិនបើអ្នកផ្សាយ <xliff:g id="SWITCHAPP">%1$s</xliff:g> ឬប្ដូរឧបករណ៍បញ្ចេញសំឡេង ការផ្សាយបច្ចុប្បន្នរបស់អ្នកនឹងបញ្ឈប់"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"ការផ្សាយ <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"ប្ដូរឧបករណ៍បញ្ចេញសំឡេង"</string> </resources> diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml index a5c97cdae7bc..f4ee0a709e57 100644 --- a/packages/SettingsLib/res/values-kn/strings.xml +++ b/packages/SettingsLib/res/values-kn/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR ಕೋಡ್ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"ಆಲಿಸುವುದಕ್ಕೆ ಪ್ರಾರಂಭಿಸಲು, ಕ್ಯಾಮರಾವನ್ನು ಕೆಳಗಿನ QR ಕೋಡ್ ಮೇಲೆ ಕೇಂದ್ರೀಕರಿಸಿ"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR ಕೋಡ್ ಮಾನ್ಯ ಫಾರ್ಮ್ಯಾಟ್ನಲ್ಲಿಲ್ಲ"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> ನ ಪ್ರಸಾರವನ್ನು ನಿಲ್ಲಿಸಬೇಕೆ?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"ನೀವು <xliff:g id="SWITCHAPP">%1$s</xliff:g> ಅನ್ನು ಪ್ರಸಾರ ಮಾಡಿದರೆ ಅಥವಾ ಔಟ್ಪುಟ್ ಅನ್ನು ಬದಲಾಯಿಸಿದರೆ, ನಿಮ್ಮ ಪ್ರಸ್ತುತ ಪ್ರಸಾರವು ಸ್ಥಗಿತಗೊಳ್ಳುತ್ತದೆ"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ಅನ್ನು ಪ್ರಸಾರ ಮಾಡಿ"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"ಔಟ್ಪುಟ್ ಅನ್ನು ಬದಲಾಯಿಸಿ"</string> </resources> diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml index ccd27c2f96b7..7a97242e9af5 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR 코드 스캔"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"아래의 QR 코드가 스캐너 가운데에 오도록 맞춘 다음 듣기를 시작하세요"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR 코드의 형식이 유효하지 않습니다."</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> 방송을 중지하시겠습니까?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> 앱을 방송하거나 출력을 변경하면 기존 방송이 중단됩니다"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> 방송"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"출력 변경"</string> </resources> diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml index fc0df561154e..8af2627c8e9c 100644 --- a/packages/SettingsLib/res/values-ky/strings.xml +++ b/packages/SettingsLib/res/values-ky/strings.xml @@ -151,7 +151,7 @@ <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Жок"</string> <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Жупташканда байланыштарыңыз менен чалуу таржымалыңызды пайдалана аласыз."</string> <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> менен жупташуу мүмкүн эмес."</string> - <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"PIN же код туура эмес болгондуктан, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> туташуу мүмкүн эмес."</string> + <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"PIN-код же сырсөз туура эмес болгондуктан, \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" түзмөгүнө туташуу мүмкүн болгон жок."</string> <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> менен байланышуу мүмкүн эмес."</string> <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Жупташтырууну <xliff:g id="DEVICE_NAME">%1$s</xliff:g> четке какты."</string> <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Компьютер"</string> @@ -236,7 +236,7 @@ <string name="enable_adb_summary" msgid="3711526030096574316">"USB компьютерге сайылганда мүчүлүштүктөрдү оңдоо режими иштейт"</string> <string name="clear_adb_keys" msgid="3010148733140369917">"USB аркылуу мүчүлүштүктөрдү аныктоо уруксатын артка кайтаруу"</string> <string name="enable_adb_wireless" msgid="6973226350963971018">"Мүчүлүштүктөрдү Wi-Fi аркылуу аныктоо"</string> - <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi‑Fi\'га туташканда, мүчүлүштүктөрдү аныктоо режими иштейт оңдоо режими"</string> + <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi‑Fi\'га туташканда, мүчүлүштүктөрдү аныктоо режими иштейт"</string> <string name="adb_wireless_error" msgid="721958772149779856">"Ката"</string> <string name="adb_wireless_settings" msgid="2295017847215680229">"Мүчүлүштүктөрдү Wi-Fi аркылуу аныктоо"</string> <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Жеткиликтүү түзмөктөрдү көрүү үчүн мүчүлүштүктөрдү Wi-Fi аркылуу аныктоону күйгүзүңүз"</string> @@ -279,8 +279,8 @@ <string name="debug_networking_category" msgid="6829757985772659599">"Тармактар"</string> <string name="wifi_display_certification" msgid="1805579519992520381">"Зымсыз мониторлорду тастыктамалоо"</string> <string name="wifi_verbose_logging" msgid="1785910450009679371">"Wi‑Fi таржымалы"</string> - <string name="wifi_scan_throttling" msgid="2985624788509913617">"Wi‑Fi тармактарын издөөнү жөнгө салуу"</string> - <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"Wi‑Fi туташуусу туруксуз MAC даректерин башаламан иретте түзүү"</string> + <string name="wifi_scan_throttling" msgid="2985624788509913617">"Wi‑Fi тармактарын издөөнү чектөө"</string> + <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"Wi-Fi тармагындагы башаламан MAC даректери"</string> <string name="mobile_data_always_on" msgid="8275958101875563572">"Мобилдик Интернет иштей берет"</string> <string name="tethering_hardware_offload" msgid="4116053719006939161">"Модем режиминде аппараттын иштешин тездетүү"</string> <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Аталышсыз Bluetooth түзмөктөрү көрүнсүн"</string> @@ -312,7 +312,7 @@ <string name="wifi_display_certification_summary" msgid="8111151348106907513">"Зымсыз мониторлорду тастыктамалоо параметрлери көрүнүп турат"</string> <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Wi-Fi тандалганда ар бир SSID үчүн RSSI көрүнүп турат"</string> <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Батареяны үнөмдөп, тармактын иштешин жакшыртат"</string> - <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Бул режим өчүрүлгөндөн кийин, түзмөк MAC дарегин башаламан иретте түзүү функциясы иштетилген тармакка туташкан сайын анын MAC дареги өзгөрүшү мүмкүн."</string> + <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Бул режим иштетилсе, түзмөктүн MAC дареги башаламан MAC даректерди түзгөн тармакка туташкан сайын өзгөрүп турушу мүмкүн."</string> <string name="wifi_metered_label" msgid="8737187690304098638">"Трафик ченелет"</string> <string name="wifi_unmetered_label" msgid="6174142840934095093">"Чектелбеген тармак"</string> <string name="select_logd_size_title" msgid="1604578195914595173">"Журнал буферинин өлчөмү"</string> @@ -398,7 +398,7 @@ <string name="immediately_destroy_activities" msgid="1826287490705167403">"Аракеттер сакталбасын"</string> <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"Колдонуучу чыгып кетери менен бардык аракеттер өчүрүлөт"</string> <string name="app_process_limit_title" msgid="8361367869453043007">"Фондогу процесстер чеги"</string> - <string name="show_all_anrs" msgid="9160563836616468726">"Фондогу \"Колдонмо жооп бербей жатат\" деп көрсөтүү"</string> + <string name="show_all_anrs" msgid="9160563836616468726">"Фондук режимдеги ANR"</string> <string name="show_all_anrs_summary" msgid="8562788834431971392">"Фондогу колдонмо жооп бербей жатат деп билдирип турат"</string> <string name="show_notification_channel_warnings" msgid="3448282400127597331">"Билдирмелер каналынын эскертүүлөрүн көрсөтүү"</string> <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"Тыюу салынган каналдын колдонмосунун жаңы билдирмелери тууралуу эскертүүлөр көрүнөт"</string> @@ -552,7 +552,7 @@ <string name="help_label" msgid="3528360748637781274">"Жардам/Пикир билдирүү"</string> <string name="storage_category" msgid="2287342585424631813">"Сактагыч"</string> <string name="shared_data_title" msgid="1017034836800864953">"Бөлүшүлгөн маалымат"</string> - <string name="shared_data_summary" msgid="5516326713822885652">"Бөлүшүлгөн маалыматты көрүп, өзгөртүү"</string> + <string name="shared_data_summary" msgid="5516326713822885652">"Бөлүшүлгөн маалыматты көрүп, өзгөртөсүз"</string> <string name="shared_data_no_blobs_text" msgid="3108114670341737434">"Бул колдонуучу менен бөлүшүлгөн маалымат жок."</string> <string name="shared_data_query_failure_text" msgid="3489828881998773687">"Бөлүшүлгөн маалыматты алууда ката кетти. Кайталоо."</string> <string name="blob_id_text" msgid="8680078988996308061">"Бөлүшүлгөн маалыматты идентификатору: <xliff:g id="BLOB_ID">%d</xliff:g>"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR кодун скандоо"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Угуп баштоо үчүн QR кодун борборго жайгаштырыңыз"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR кодунун форматы жараксыз"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда кабарлоо токтотулсунбу?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Эгер <xliff:g id="SWITCHAPP">%1$s</xliff:g> колдонмосунда кабарласаңыз же аудионун чыгуусун өзгөртсөңүз, учурдагы кабарлоо токтотулат"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> колдонмосунда кабарлоо"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Аудионун чыгуусун өзгөртүү"</string> </resources> diff --git a/packages/SettingsLib/res/values-lo/arrays.xml b/packages/SettingsLib/res/values-lo/arrays.xml index 4d9f5d9875e9..56a9741d3419 100644 --- a/packages/SettingsLib/res/values-lo/arrays.xml +++ b/packages/SettingsLib/res/values-lo/arrays.xml @@ -76,7 +76,7 @@ <item msgid="1963366694959681026">"avrcp16"</item> </string-array> <string-array name="bluetooth_map_versions"> - <item msgid="8786402640610987099">"MAP 1.2 (Default)"</item> + <item msgid="8786402640610987099">"MAP 1.2 (ຄ່າເລີ່ມຕົ້ນ)"</item> <item msgid="6817922176194686449">"MAP 1.3"</item> <item msgid="3423518690032737851">"MAP 1.4"</item> </string-array> diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml index 9ad508791733..5c0f1921b665 100644 --- a/packages/SettingsLib/res/values-lo/strings.xml +++ b/packages/SettingsLib/res/values-lo/strings.xml @@ -393,7 +393,7 @@ <string name="window_animation_scale_title" msgid="5236381298376812508">"ຂະໜາດໜ້າຈໍຂອງອະນິເມຊັນ"</string> <string name="transition_animation_scale_title" msgid="1278477690695439337">"ຂະໜາດສະຫຼັບອະນິເມຊັນ"</string> <string name="animator_duration_scale_title" msgid="7082913931326085176">"ໄລຍະເວລາອະນິເມຊັນ"</string> - <string name="overlay_display_devices_title" msgid="5411894622334469607">"ຈຳລອງຈໍສະແດງຜົນທີ່ສອງ"</string> + <string name="overlay_display_devices_title" msgid="5411894622334469607">"ຈຳລອງຈໍສະແດງຜົນທີສອງ"</string> <string name="debug_applications_category" msgid="5394089406638954196">"ແອັບ"</string> <string name="immediately_destroy_activities" msgid="1826287490705167403">"ບໍ່ຕ້ອງຮັກສາການເຄື່ອນໄຫວ"</string> <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"ລຶບທຸກການເຄື່ອນໄຫວທັນທີທີ່ຜູ້ໃຊ້ອອກຈາກມັນ"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"ສະແກນລະຫັດ QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"ເພື່ອເລີ່ມການຟັງ, ໃຫ້ວາງລະຫັດ QR ທາງລຸ່ມນີ້ໄວ້ທາງກາງ"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"ຮູບແບບລະຫັດ QR ບໍ່ຖືກຕ້ອງ"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"ຢຸດການອອກອາກາດ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"ຫາກທ່ານອອກອາກາດ <xliff:g id="SWITCHAPP">%1$s</xliff:g> ຫຼື ປ່ຽນເອົ້າພຸດ, ການອອກອາກາດປັດຈຸບັນຂອງທ່ານຈະຢຸດ"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"ອອກອາກາດ <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"ປ່ຽນເອົ້າພຸດ"</string> </resources> diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml index 6f2f7042064a..250d24af0d38 100644 --- a/packages/SettingsLib/res/values-lt/strings.xml +++ b/packages/SettingsLib/res/values-lt/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR kodo nuskaitymas"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Jei norite pradėti klausyti, nustatykite toliau pateiktą QR kodą per vidurį"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR kodas netinkamo formato"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Sustabdyti „<xliff:g id="APP_NAME">%1$s</xliff:g>“ transliaciją?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Jei transliuosite „<xliff:g id="SWITCHAPP">%1$s</xliff:g>“ arba pakeisite išvestį, dabartinė transliacija bus sustabdyta"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Transliuoti „<xliff:g id="SWITCHAPP">%1$s</xliff:g>“"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Keisti išvestį"</string> </resources> diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml index 0b3eb9487842..f72ba8e996fe 100644 --- a/packages/SettingsLib/res/values-lv/strings.xml +++ b/packages/SettingsLib/res/values-lv/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Kvadrātkoda skenēšana"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Lai sāktu klausīties, centrējiet tālāk norādīto kvadrātkodu."</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"Kvadrātkoda formāts nav derīgs."</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Vai apturēt lietotnes <xliff:g id="APP_NAME">%1$s</xliff:g> apraidīšanu?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Ja sāksiet lietotnes <xliff:g id="SWITCHAPP">%1$s</xliff:g> apraidīšanu vai mainīsiet izvadi, pašreizējā apraide tiks apturēta"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Lietotnes <xliff:g id="SWITCHAPP">%1$s</xliff:g> apraide"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Izvades maiņa"</string> </resources> diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml index bbd792e29ae1..376452c78d4a 100644 --- a/packages/SettingsLib/res/values-mk/strings.xml +++ b/packages/SettingsLib/res/values-mk/strings.xml @@ -266,7 +266,7 @@ <string name="bugreport_in_power" msgid="8664089072534638709">"Кратенка за извештај за грешка"</string> <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Прикажи копче во менито за вклучување за да се направи извештај за грешка"</string> <string name="keep_screen_on" msgid="1187161672348797558">"Остани во активен режим"</string> - <string name="keep_screen_on_summary" msgid="1510731514101925829">"Екранот никогаш нема да биде во режим на штедење додека се полни"</string> + <string name="keep_screen_on_summary" msgid="1510731514101925829">"Екранот никогаш нема да биде во режим на спиење додека се полни"</string> <string name="bt_hci_snoop_log" msgid="7291287955649081448">"Овозможи Bluetooth HCI за евиденција на пресретнување пакети"</string> <string name="bt_hci_snoop_log_summary" msgid="6808538971394092284">"Снимај Bluetooth-пакети. (Вклучи Bluetooth по промената на поставкава)"</string> <string name="oem_unlock_enable" msgid="5334869171871566731">"Отклучување со OEM"</string> @@ -337,7 +337,7 @@ <string name="dev_settings_warning_message" msgid="37741686486073668">"Овие поставки се наменети само за употреба за развој. Тие може да предизвикаат уредот и апликациите во него да се расипат или да се однесуваат необично."</string> <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"Потврди апликации преку USB"</string> <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Провери апликации инсталирани преку ADB/ADT за штетно однесување."</string> - <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Уредите со Bluetooth без имиња (само MAC-адреси) ќе се прикажуваат"</string> + <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"Ќе се прикажуваат уредите со Bluetooth без имиња (само MAC-адреси)"</string> <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Ја оневозможува функцијата за апсолутна јачина на звук преку Bluetooth во случај кога ќе настанат проблеми со далечинските уреди, како на пр., неприфатливо силен звук или недоволна контрола."</string> <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"Ја овозможува функцијата Bluetooth Gabeldorsche."</string> <string name="enhanced_connectivity_summary" msgid="1576414159820676330">"Ја овозможува функцијата „Подобрена поврзливост“."</string> @@ -352,7 +352,7 @@ <string name="select_application" msgid="2543228890535466325">"Избери апликација"</string> <string name="no_application" msgid="9038334538870247690">"Ништо"</string> <string name="wait_for_debugger" msgid="7461199843335409809">"Почекај ја програмата за отстранување грешки"</string> - <string name="wait_for_debugger_summary" msgid="6846330006113363286">"Пред да се изврши, апликација за отстранување грешки чека програмата за отстранување грешки да се закачи"</string> + <string name="wait_for_debugger_summary" msgid="6846330006113363286">"Пред да се изврши, апликацијата во која се отстрануваат грешки чека да се закачи програмата за отстранување грешки"</string> <string name="debug_input_category" msgid="7349460906970849771">"Внесување"</string> <string name="debug_drawing_category" msgid="5066171112313666619">"Цртање"</string> <string name="debug_hw_drawing_category" msgid="5830815169336975162">"Хардверско забрзување"</string> @@ -378,7 +378,7 @@ <string name="usb_audio_disable_routing" msgid="3367656923544254975">"Исклучи USB-пренасочување"</string> <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"Исклучи автоматско пренасочување до USB-аудиоуреди"</string> <string name="debug_layout" msgid="1659216803043339741">"Прикажи граници на слој"</string> - <string name="debug_layout_summary" msgid="8825829038287321978">"Прикажи граници на клип, маргини, итн."</string> + <string name="debug_layout_summary" msgid="8825829038287321978">"Прикажи граници на клип, маргини итн."</string> <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Принудно користи RTL за насока"</string> <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Принудно постави насока на распоред на екранот во RTL за сите локални стандарди"</string> <string name="window_blurs" msgid="6831008984828425106">"Дозволи замаглување прозорец"</string> @@ -483,7 +483,7 @@ <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Бавно полнење"</string> <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Се полни безжично"</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="3371084153747234837">"Поврзано, не се полни"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Полна"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Целосно полна"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Контролирано од администраторот"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Скенирајте QR-код"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"За да започне слушањето, центрирајте го QR-кодот долу"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR-кодот не е во важечки формат"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Да се прекине емитувањето на <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Ако емитувате на <xliff:g id="SWITCHAPP">%1$s</xliff:g> или го промените излезот, тековното емитување ќе запре"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Емитување на <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Променете излез"</string> </resources> diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml index a8a6bec79fba..e69d25f65c70 100644 --- a/packages/SettingsLib/res/values-ml/strings.xml +++ b/packages/SettingsLib/res/values-ml/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR കോഡ് സ്കാൻ ചെയ്യുക"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"കേട്ട് തുടങ്ങാൻ ചുവടെയുള്ള QR കോഡിലേക്ക് കേന്ദ്രീകരിക്കുക"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR കോഡ് ഫോർമാറ്റ് അസാധുവാണ്"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> ബ്രോഡ്കാസ്റ്റ് ചെയ്യുന്നത് അവസാനിപ്പിക്കണോ?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"നിങ്ങൾ <xliff:g id="SWITCHAPP">%1$s</xliff:g> ബ്രോഡ്കാസ്റ്റ് ചെയ്യുകയോ ഔട്ട്പുട്ട് മാറ്റുകയോ ചെയ്താൽ നിങ്ങളുടെ നിലവിലുള്ള ബ്രോഡ്കാസ്റ്റ് അവസാനിക്കും"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ബ്രോഡ്കാസ്റ്റ് ചെയ്യുക"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"ഔട്ട്പുട്ട് മാറ്റുക"</string> </resources> diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml index fe3577253e55..cd41b81381d1 100644 --- a/packages/SettingsLib/res/values-mn/strings.xml +++ b/packages/SettingsLib/res/values-mn/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR код скан хийх"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Сонсож эхлэхийн тулд доорх QR кодыг голлуулаарай"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR код буруу форматтай байна"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g>-г нэвтрүүлэхээ зогсоох уу?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Хэрэв та <xliff:g id="SWITCHAPP">%1$s</xliff:g>-г нэвтрүүлсэн эсвэл гаралтыг өөрчилсөн бол таны одоогийн нэвтрүүлэлтийг зогсооно"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g>-г нэвтрүүлэх"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Гаралтыг өөрчлөх"</string> </resources> diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml index 9e483c2cfa7c..4006665cb12e 100644 --- a/packages/SettingsLib/res/values-mr/strings.xml +++ b/packages/SettingsLib/res/values-mr/strings.xml @@ -190,7 +190,7 @@ <string name="tts_default_pitch_title" msgid="6988592215554485479">"पिच"</string> <string name="tts_default_pitch_summary" msgid="9132719475281551884">"संश्लेषित उच्चारांच्या आवाजास प्रभावित करते"</string> <string name="tts_default_lang_title" msgid="4698933575028098940">"भाषा"</string> - <string name="tts_lang_use_system" msgid="6312945299804012406">"सिस्टम भाषा वापरा"</string> + <string name="tts_lang_use_system" msgid="6312945299804012406">"सिस्टीमची भाषा वापरा"</string> <string name="tts_lang_not_selected" msgid="7927823081096056147">"भाषा निवडलेली नाही"</string> <string name="tts_default_lang_summary" msgid="9042620014800063470">"बोललेल्या मजकुरासाठी भाषा-विशिष्ट आवाज सेट करते"</string> <string name="tts_play_example_title" msgid="1599468547216481684">"उदाहरण ऐका"</string> @@ -520,7 +520,7 @@ <string name="ims_reg_status_not_registered" msgid="2989287366045704694">"नोंदवलेले नाही"</string> <string name="status_unavailable" msgid="5279036186589861608">"उपलब्ध नाही"</string> <string name="wifi_status_mac_randomized" msgid="466382542497832189">"MAC रँडमाइझ केला आहे"</string> - <string name="wifi_tether_connected_summary" msgid="5282919920463340158">"{count,plural, =0{0 device connected}=1{एक डिव्हाइस कनेक्ट केले}other{# डिव्हाइस कनेक्ट केली}}"</string> + <string name="wifi_tether_connected_summary" msgid="5282919920463340158">"{count,plural, =0{0 डिव्हाइस कनेक्ट केले}=1{एक डिव्हाइस कनेक्ट केले}other{# डिव्हाइस कनेक्ट केली}}"</string> <string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"जास्त वेळ."</string> <string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"कमी वेळ."</string> <string name="cancel" msgid="5665114069455378395">"रद्द करा"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR कोड स्कॅन करा"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"ऐकणे सुरू करण्यासाठी, खालील QR कोड मध्यभागी ठेवा"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR कोडचा फॉरमॅट चुकीचा आहे"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> चे प्रसारण थांबवायचे आहे का?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"तुम्ही <xliff:g id="SWITCHAPP">%1$s</xliff:g> चे प्रसारण केल्यास किंवा आउटपुट बदलल्यास, तुमचे सध्याचे प्रसारण बंद होईल"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> चे प्रसारण करा"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"आउटपूट बदला"</string> </resources> diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml index c989def748c2..8a2fc2b0f450 100644 --- a/packages/SettingsLib/res/values-ms/strings.xml +++ b/packages/SettingsLib/res/values-ms/strings.xml @@ -151,7 +151,7 @@ <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Batal"</string> <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Berpasangan memberi anda akses kepada kenalan dan sejarah panggilan apabila disambungkan."</string> <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Tidak dapat berpasangan dengan <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> - <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Tidak dapat berpasangan dengan <xliff:g id="DEVICE_NAME">%1$s</xliff:g> kerana PIN atau kunci laluan yang salah."</string> + <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Tidak dapat berganding dengan <xliff:g id="DEVICE_NAME">%1$s</xliff:g> kerana PIN atau kunci laluan yang salah."</string> <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Tidak boleh berkomunikasi dengan <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Pasangan ditolak oleh <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Komputer"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Imbas kod QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Untuk mula mendengar, pusatkan kod QR di bawah"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"Kod QR bukan dalam format yang sah"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Hentikan siaran <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Jika anda siarkan <xliff:g id="SWITCHAPP">%1$s</xliff:g> atau tukarkan output, siaran semasa anda akan berhenti"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Siarkan <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Tukar output"</string> </resources> diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml index a6749ee089df..98bac84ac706 100644 --- a/packages/SettingsLib/res/values-my/strings.xml +++ b/packages/SettingsLib/res/values-my/strings.xml @@ -656,12 +656,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR ကုဒ်ကို စကင်ဖတ်ရန်"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"စတင်နားဆင်ရန် အောက်ရှိ QR ကုဒ်ကို အလယ်တွင်ထားပါ"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR ကုဒ်သည် မှန်ကန်သောဖော်မက် မဟုတ်ပါ"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> ထုတ်လွှင့်ခြင်းကို ရပ်မလား။"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ကို ထုတ်လွှင့်သောအခါ (သို့) အထွက်ကို ပြောင်းသောအခါ သင့်လက်ရှိထုတ်လွှင့်ခြင်း ရပ်သွားမည်"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ထုတ်လွှင့်ခြင်း"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"အထွက်ကို ပြောင်းခြင်း"</string> </resources> diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index 57178fd645b4..13bdd7e90dbc 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Skann QR-koden"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"For å begynne å lytte, midtstill QR-koden nedenfor"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR-koden er ikke i et gyldig format"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Vil du stoppe kringkastingen av <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Hvis du kringkaster <xliff:g id="SWITCHAPP">%1$s</xliff:g> eller endrer utgangen, stopper den nåværende kringkastingen din"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Kringkast <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Endre utgang"</string> </resources> diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml index 51d5a2ce3618..30401ace32ed 100644 --- a/packages/SettingsLib/res/values-ne/strings.xml +++ b/packages/SettingsLib/res/values-ne/strings.xml @@ -357,7 +357,7 @@ <string name="debug_drawing_category" msgid="5066171112313666619">"रेखाचित्र"</string> <string name="debug_hw_drawing_category" msgid="5830815169336975162">"हार्डवेयरले बढाएको रेन्डरिङ"</string> <string name="media_category" msgid="8122076702526144053">"मिडिया"</string> - <string name="debug_monitoring_category" msgid="1597387133765424994">"अनुगमन गर्दै"</string> + <string name="debug_monitoring_category" msgid="1597387133765424994">"अनुगमन गरिँदै छ"</string> <string name="strict_mode" msgid="889864762140862437">"स्ट्रिक्ट मोड अन गरियोस्"</string> <string name="strict_mode_summary" msgid="1838248687233554654">"एपले मुख्य थ्रेडमा लामा गतिविधि गर्दा स्क्रिन फ्ल्यास गरियोस्"</string> <string name="pointer_location" msgid="7516929526199520173">"पोइन्टरको स्थान"</string> @@ -402,7 +402,7 @@ <string name="show_all_anrs_summary" msgid="8562788834431971392">"ब्याकग्राउन्डका एपको हकमा \'नचलिरहेका एप\' सन्देश देखाइयोस्"</string> <string name="show_notification_channel_warnings" msgid="3448282400127597331">"सूचना च्यानलसम्बन्धी चेतावनी देखाइयोस्"</string> <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"एपले मान्य च्यानलबिना सूचना पोस्ट गर्दा स्क्रिनमा चेतावनी देखाइयोस्"</string> - <string name="force_allow_on_external" msgid="9187902444231637880">"एपलाई बहिरी मेमोरीमा पनि चल्ने दिइयोस्"</string> + <string name="force_allow_on_external" msgid="9187902444231637880">"एपलाई बहिरी मेमोरीमा पनि चल्न दिइयोस्"</string> <string name="force_allow_on_external_summary" msgid="8525425782530728238">"तोकिएको नियमको ख्याल नगरी एपलाई बाह्य भण्डारणमा चल्ने बनाइयोस्"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"बलपूर्वक एपहरूको आकार मिलाउन मिल्ने बनाइयोस्"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"तोकिएको नियमको ख्याल नगरी एपलाई एकभन्दा बढी विन्डोमा रिसाइज गर्न सकिने बनाइयोस्।"</string> @@ -442,7 +442,7 @@ <string name="select_webview_provider_toast_text" msgid="8512254949169359848">"यो छनोट अब मान्य छैन। फेरि प्रयास गर्नुहोस्।"</string> <string name="picture_color_mode" msgid="1013807330552931903">"चित्र रङ्ग मोड"</string> <string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB प्रयोग गर्नुहोस्"</string> - <string name="daltonizer_mode_disabled" msgid="403424372812399228">"असक्षम गरिएको छ"</string> + <string name="daltonizer_mode_disabled" msgid="403424372812399228">"अफ गरिएको छ"</string> <string name="daltonizer_mode_monochromacy" msgid="362060873835885014">"मोनोक्रोमेसी"</string> <string name="daltonizer_mode_deuteranomaly" msgid="3507284319584683963">"ड्युटरएनोमली (रातो-हरियो)"</string> <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"प्रोटानेमली (रातो, हरियो)"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR कोड स्क्यान गर्नुहोस्"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"अडियो सुन्न तलको QR कोडलाई केन्द्र भागमा पार्नुहोस्"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR कोडको फर्म्याट वैध छैन"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> ब्रोडकास्ट गर्न छाड्ने हो?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"तपाईंले <xliff:g id="SWITCHAPP">%1$s</xliff:g> ब्रोडकास्ट गर्नुभयो वा आउटपुट परिवर्तन गर्नुभयो भने तपाईंको हालको ब्रोडकास्ट रोकिने छ"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ब्रोडकास्ट गर्नुहोस्"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"आउटपुट परिवर्तन गर्नुहोस्"</string> </resources> diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml index 8af013617985..c5065cb364bb 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -570,7 +570,7 @@ <string name="user_add_profile_item_title" msgid="3111051717414643029">"Beperkt profiel"</string> <string name="user_add_user_title" msgid="5457079143694924885">"Nieuwe gebruiker toevoegen?"</string> <string name="user_add_user_message_long" msgid="1527434966294733380">"Je kunt dit apparaat met anderen delen door extra gebruikers te maken. Elke gebruiker heeft een eigen profiel met zelf gekozen apps, achtergrond, enzovoort. Gebruikers kunnen ook apparaatinstellingen aanpassen die van invloed zijn op alle gebruikers, zoals wifi.\n\nWanneer je een nieuwe gebruiker toevoegt, moet die persoon een eigen profiel instellen.\n\nElke gebruiker kan apps updaten voor alle andere gebruikers. Toegankelijkheidsinstellingen en -services worden mogelijk niet overgezet naar de nieuwe gebruiker."</string> - <string name="user_add_user_message_short" msgid="3295959985795716166">"Wanneer je een nieuwe gebruiker toevoegt, moet die persoon zijn eigen profiel instellen.\n\nElke gebruiker kan apps updaten voor alle andere gebruikers."</string> + <string name="user_add_user_message_short" msgid="3295959985795716166">"Wanneer je een nieuwe gebruiker toevoegt, moet die persoon diens eigen profiel instellen.\n\nElke gebruiker kan apps updaten voor alle andere gebruikers."</string> <string name="user_setup_dialog_title" msgid="8037342066381939995">"Gebruiker nu instellen?"</string> <string name="user_setup_dialog_message" msgid="269931619868102841">"Zorg ervoor dat de persoon het apparaat kan overnemen om een profiel in te stellen"</string> <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"Profiel nu instellen?"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR-code scannen"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Centreer de onderstaande QR-code om te beginnen met luisteren"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR-code heeft geen geldige indeling"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Uitzending van <xliff:g id="APP_NAME">%1$s</xliff:g> stopzetten?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Als je <xliff:g id="SWITCHAPP">%1$s</xliff:g> uitzendt of de uitvoer wijzigt, wordt je huidige uitzending gestopt"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> uitzenden"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Uitvoer wijzigen"</string> </resources> diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml index 908fa9686aab..337dd79735f6 100644 --- a/packages/SettingsLib/res/values-or/strings.xml +++ b/packages/SettingsLib/res/values-or/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR କୋଡ ସ୍କାନ କରନ୍ତୁ"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"ଶୁଣିବା ଆରମ୍ଭ କରିବା ପାଇଁ, ନିମ୍ନରେ ଥିବା QR କୋଡକୁ କେନ୍ଦ୍ରରେ ରଖନ୍ତୁ"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR କୋଡ ଏକ ବୈଧ ଫର୍ମାଟ ନୁହେଁ"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> ବ୍ରଡକାଷ୍ଟ କରିବା ବନ୍ଦ କରିବେ?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"ଯଦି ଆପଣ <xliff:g id="SWITCHAPP">%1$s</xliff:g> ବ୍ରଡକାଷ୍ଟ କରନ୍ତି କିମ୍ବା ଆଉଟପୁଟ ବଦଳାନ୍ତି, ତେବେ ଆପଣଙ୍କ ବର୍ତ୍ତମାନର ବ୍ରଡକାଷ୍ଟ ବନ୍ଦ ହୋଇଯିବ"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ବ୍ରଡକାଷ୍ଟ କରନ୍ତୁ"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"ଆଉଟପୁଟ ବଦଳାନ୍ତୁ"</string> </resources> diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml index ac953657868b..0da516c80698 100644 --- a/packages/SettingsLib/res/values-pa/strings.xml +++ b/packages/SettingsLib/res/values-pa/strings.xml @@ -309,9 +309,9 @@ <string name="private_dns_mode_provider" msgid="3619040641762557028">"ਨਿੱਜੀ DNS ਪ੍ਰਦਾਨਕ ਹੋਸਟਨਾਮ"</string> <string name="private_dns_mode_provider_hostname_hint" msgid="6564868953748514595">"DNS ਪ੍ਰਦਾਨਕ ਦਾ ਹੋਸਟਨਾਮ ਦਾਖਲ ਕਰੋ"</string> <string name="private_dns_mode_provider_failure" msgid="8356259467861515108">"ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string> - <string name="wifi_display_certification_summary" msgid="8111151348106907513">"ਵਾਇਰਲੈੱਸ ਡਿਸਪਲੇ ਪ੍ਰਮਾਣੀਕਰਨ ਲਈ ਚੋਣਾਂ ਪ੍ਰਦਰਸ਼ਿਤ ਕਰੋ"</string> + <string name="wifi_display_certification_summary" msgid="8111151348106907513">"ਵਾਇਰਲੈੱਸ ਡਿਸਪਲੇ ਪ੍ਰਮਾਣੀਕਰਨ ਲਈ ਵਿਕਲਪ ਦਿਖਾਓ"</string> <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"ਵਾਈ‑ਫਾਈ ਲੌਗਿੰਗ ਪੱਧਰ ਵਧਾਓ, ਵਾਈ‑ਫਾਈ ਚੋਣਕਾਰ ਵਿੱਚ ਪ੍ਰਤੀ SSID RSSI ਦਿਖਾਓ"</string> - <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਘਟਾ ਕੇ ਨੈੱਟਵਰਕ ਕਾਰਗੁਜ਼ਾਰੀ ਨੂੰ ਬਿਹਤਰ ਬਣਾਉਂਦਾ ਹੈ"</string> + <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"ਤੇਜ਼ੀ ਨਾਲ ਹੋਣ ਵਾਲੇ ਬੈਟਰੀ ਖਰਚ ਨੂੰ ਘਟਾ ਕੇ ਨੈੱਟਵਰਕ ਕਾਰਗੁਜ਼ਾਰੀ ਨੂੰ ਬਿਹਤਰ ਬਣਾਉਂਦਾ ਹੈ"</string> <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"ਜਦੋਂ ਇਹ ਮੋਡ ਚਾਲੂ ਹੁੰਦਾ ਹੈ, ਤਾਂ ਇਸ ਡੀਵਾਈਸ ਦਾ MAC ਪਤਾ ਹਰ ਵਾਰ ਬਦਲ ਸਕਦਾ ਹੈ ਜਦੋਂ ਇਹ ਕਿਸੇ ਅਜਿਹੇ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਹੁੰਦਾ ਹੈ ਜਿਸ ਵਿੱਚ MAC ਬੇਤਰਤੀਬਵਾਰ ਚਾਲੂ ਹੁੰਦਾ ਹੈ।"</string> <string name="wifi_metered_label" msgid="8737187690304098638">"ਮੀਟਰਬੱਧ ਕੀਤਾ ਗਿਆ"</string> <string name="wifi_unmetered_label" msgid="6174142840934095093">"ਗੈਰ-ਮੀਟਰਬੱਧ ਕੀਤਾ ਗਿਆ"</string> @@ -326,7 +326,7 @@ <string name="allow_mock_location" msgid="2102650981552527884">"ਨਕਲੀ ਨਿਰਧਾਰਿਤ ਸਥਾਨਾਂ ਦੀ ਆਗਿਆ ਦਿਓ"</string> <string name="allow_mock_location_summary" msgid="179780881081354579">"ਨਕਲੀ ਨਿਰਧਾਰਿਤ ਸਥਾਨਾਂ ਦੀ ਆਗਿਆ ਦਿਓ"</string> <string name="debug_view_attributes" msgid="3539609843984208216">"\'ਵਿਸ਼ੇਸ਼ਤਾ ਨਿਰੀਖਣ ਦੇਖੋ\' ਨੂੰ ਚਾਲੂ ਕਰੋ"</string> - <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"ਵਾਈ‑ਫਾਈ ਕਿਰਿਆਸ਼ੀਲ ਹੋਣ \'ਤੇ ਵੀ ਹਮੇਸ਼ਾਂ ਮੋਬਾਈਲ ਡਾਟਾ ਨੂੰ ਕਿਰਿਆਸ਼ੀਲ ਰੱਖੋ(ਤੇਜ਼ ਨੈੱਟਵਰਕ ਸਵਿੱਚਿੰਗ ਲਈ)।"</string> + <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"ਵਾਈ‑ਫਾਈ ਕਿਰਿਆਸ਼ੀਲ ਹੋਣ \'ਤੇ ਵੀ ਹਮੇਸ਼ਾਂ ਮੋਬਾਈਲ ਡਾਟਾ ਨੂੰ ਕਿਰਿਆਸ਼ੀਲ ਰੱਖੋ (ਤੇਜ਼ ਨੈੱਟਵਰਕ ਸਵਿੱਚਿੰਗ ਲਈ)।"</string> <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"ਉਪਲਬਧ ਹੋਣ \'ਤੇ ਟੈਦਰਿੰਗ ਹਾਰਡਵੇਅਰ ਐਕਸੈੱਲਰੇਸ਼ਨ ਵਰਤੋ"</string> <string name="adb_warning_title" msgid="7708653449506485728">"ਕੀ USB ਡੀਬਗਿੰਗ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string> <string name="adb_warning_message" msgid="8145270656419669221">"USB ਡੀਬਗਿੰਗ ਸਿਰਫ਼ ਵਿਕਾਸ ਮੰਤਵਾਂ ਲਈ ਹੁੰਦੀ ਹੈ। ਇਸਨੂੰ ਆਪਣੇ ਕੰਪਿਊਟਰ ਅਤੇ ਆਪਣੇ ਡੀਵਾਈਸ ਵਿਚਕਾਰ ਡਾਟਾ ਕਾਪੀ ਕਰਨ ਲਈ ਵਰਤੋ, ਸੂਚਨਾ ਦੇ ਬਿਨਾਂ ਆਪਣੇ ਡੀਵਾਈਸ ਤੇ ਐਪਾਂ ਸਥਾਪਤ ਕਰੋ ਅਤੇ ਲੌਗ ਡਾਟਾ ਪੜ੍ਹੋ।"</string> @@ -336,7 +336,7 @@ <string name="dev_settings_warning_title" msgid="8251234890169074553">"ਕੀ ਵਿਕਾਸ ਸੈਟਿੰਗਾਂ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string> <string name="dev_settings_warning_message" msgid="37741686486073668">"ਇਹ ਸੈਟਿੰਗਾਂ ਕੇਵਲ ਵਿਕਾਸਕਾਰ ਦੀ ਵਰਤੋਂ ਲਈ ਹਨ। ਇਹ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਅਤੇ ਇਸਤੇ ਮੌਜੂਦ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਬ੍ਰੇਕ ਕਰਨ ਜਾਂ ਦੁਰਵਿਵਹਾਰ ਕਰਨ ਦਾ ਕਾਰਨ ਬਣ ਸਕਦੇ ਹਨ।"</string> <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"USB \'ਤੇ ਐਪਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ"</string> - <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ਹਾਨੀਕਾਰਕ ਵਿਵਹਾਰ ਲਈ ADB/ADT ਰਾਹੀਂ ਸਥਾਪਤ ਕੀਤੀਆਂ ਐਪਾਂ ਦੀ ਜਾਂਚ ਕਰੋ।"</string> + <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"ADB/ADT ਰਾਹੀਂ ਸਥਾਪਤ ਕੀਤੀਆਂ ਐਪਾਂ ਦੀ ਹਾਨੀਕਾਰਕ ਵਿਵਹਾਰ ਲਈ ਜਾਂਚ ਕਰੋ।"</string> <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"ਅਨਾਮ ਬਲੂਟੁੱਥ ਡੀਵਾਈਸਾਂ ਦਿਖਾਈਆਂ ਜਾਣਗੀਆਂ (ਸਿਰਫ਼ MAC ਪਤੇ)"</string> <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"ਰਿਮੋਟ ਡੀਵਾਈਸਾਂ ਨਾਲ ਅਵਾਜ਼ੀ ਸਮੱਸਿਆਵਾਂ ਜਿਵੇਂ ਕਿ ਨਾ ਪਸੰਦ ਕੀਤੀ ਜਾਣ ਵਾਲੀ ਉੱਚੀ ਅਵਾਜ਼ ਜਾਂ ਕੰਟਰੋਲ ਦੀ ਕਮੀ ਵਰਗੀ ਹਾਲਤ ਵਿੱਚ ਬਲੂਟੁੱਥ ਪੂਰਨ ਅਵਾਜ਼ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਬੰਦ ਕਰਦਾ ਹੈ।"</string> <string name="bluetooth_enable_gabeldorsche_summary" msgid="2054730331770712629">"ਬਲੂਟੁੱਥ Gabeldorsche ਵਿਸ਼ੇਸ਼ਤਾ ਸਟੈਕ ਨੂੰ ਚਾਲੂ ਕਰਦਾ ਹੈ।"</string> @@ -367,9 +367,9 @@ <string name="show_screen_updates" msgid="2078782895825535494">"ਸਰਫ਼ੇਸ ਅੱਪਡੇਟ ਦਿਖਾਓ"</string> <string name="show_screen_updates_summary" msgid="2126932969682087406">"ਅੱਪਡੇਟ ਹੋਣ \'ਤੇ, ਸਮੁੱਚੀਆਂ ਵਿੰਡੋ ਸਰਫ਼ੇਸਾਂ ਫਲੈਸ਼ ਕਰੋ"</string> <string name="show_hw_screen_updates" msgid="2021286231267747506">"\'ਅੱਪਡੇਟ ਦੇਖੋ\' ਨੂੰ ਦਿਖਾਓ"</string> - <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"ਡ੍ਰਾ ਕੀਤੇ ਜਾਣ \'ਤੇ ਵਿੰਡੋਜ਼ ਦੇ ਅੰਦਰ ਦ੍ਰਿਸ਼ ਫਲੈਸ਼ ਕਰੋ"</string> + <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="show_hw_layers_updates_summary" msgid="5850955890493054618">"ਅੱਪਡੇਟ ਹੋਣ ਤੋਂ ਬਾਅਦ ਹਾਰਡਵੇਅਰ ਤਹਿਆਂ ਨੂੰ ਹਰਾ ਕਰੋ"</string> <string name="debug_hw_overdraw" msgid="8944851091008756796">"GPU ਓਵਰਡ੍ਰਾ ਡੀਬੱਗ ਕਰੋ"</string> <string name="disable_overlays" msgid="4206590799671557143">"HW ਓਵਰਲੇ ਨੂੰ ਬੰਦ ਕਰੋ"</string> <string name="disable_overlays_summary" msgid="1954852414363338166">"ਸਕ੍ਰੀਨ ਕੰਪੋਜ਼ਿਟਿੰਗ ਲਈ ਹਮੇਸ਼ਾਂ GPU ਵਰਤੋ"</string> @@ -382,7 +382,7 @@ <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"ਸੱਜੇ ਤੋਂ ਖੱਬੇ ਵਾਲਾ ਖਾਕਾ ਲਾਗੂ ਕਰੋ"</string> <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"ਸਾਰੀਆਂ ਭਾਸ਼ਾਵਾਂ ਲਈ ਸਕ੍ਰੀਨ \'ਤੇ ਸੱਜੇ ਤੋਂ ਖੱਬੇ ਵਾਲਾ ਖਾਕਾ ਲਾਗੂ ਕਰੋ"</string> <string name="window_blurs" msgid="6831008984828425106">"ਵਿੰਡੋ-ਪੱਧਰ \'ਤੇ ਧੁੰਦਲਾ ਕਰਨ ਦਿਓ"</string> - <string name="force_msaa" msgid="4081288296137775550">"4x MSAA ਤੇ ਜ਼ੋਰ ਪਾਓ"</string> + <string name="force_msaa" msgid="4081288296137775550">"4x MSAA ਜ਼ਬਰਦਸਤੀ ਲਾਗੂ ਕਰੋ"</string> <string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 ਐਪਾਂ ਵਿੱਚ 4x MSAA ਨੂੰ ਚਾਲੂ ਕਰੋ"</string> <string name="show_non_rect_clip" msgid="7499758654867881817">"ਗੈਰ-ਆਇਤਾਕਾਰ ਕਲਿੱਪ ਓਪਰੇਸ਼ਨ ਡੀਬੱਗ ਕਰੋ"</string> <string name="track_frame_time" msgid="522674651937771106">"ਪ੍ਰੋਫਾਈਲ HWUI ਰੈਂਡਰਿੰਗ"</string> @@ -404,7 +404,7 @@ <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"ਐਪ ਵੱਲੋਂ ਵੈਧ ਚੈਨਲ ਤੋਂ ਬਿਨਾਂ ਸੂਚਨਾ ਪੋਸਟ ਕਰਨ \'ਤੇ ਸਕ੍ਰੀਨ \'ਤੇ ਚਿਤਾਵਨੀ ਦਿਖਾਉਂਦੀ ਹੈ"</string> <string name="force_allow_on_external" msgid="9187902444231637880">"ਐਪਾਂ ਨੂੰ ਜ਼ਬਰਦਸਤੀ ਬਾਹਰੀ ਸਟੋਰੇਜ \'ਤੇ ਆਗਿਆ ਦਿਓ"</string> <string name="force_allow_on_external_summary" msgid="8525425782530728238">"ਮੈਨੀਫੈਸਟ ਮੁੱਲਾਂ ਦੀ ਪਰਵਾਹ ਕੀਤੇ ਬਿਨਾਂ, ਕਿਸੇ ਵੀ ਐਪ ਨੂੰ ਬਾਹਰੀ ਸਟੋਰੇਜ \'ਤੇ ਲਿਖਣ ਦੇ ਯੋਗ ਬਣਾਉਂਦੀ ਹੈ"</string> - <string name="force_resizable_activities" msgid="7143612144399959606">"ਆਕਾਰ ਬਦਲਣਯੋਗ ਬਣਾਉਣ ਲਈ ਸਰਗਰਮੀਆਂ \'ਤੇ ਜ਼ੋਰ ਦਿਓ"</string> + <string name="force_resizable_activities" msgid="7143612144399959606">"ਵਿੰਡੋ ਮੁਤਾਬਕ ਸਰਗਰਮੀਆਂ ਦਾ ਆਕਾਰ ਬਦਲ ਦਿਓ"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"ਮੈਨੀਫ਼ੈਸਟ ਮੁੱਲਾਂ ਦੀ ਪਰਵਾਹ ਕੀਤੇ ਬਿਨਾਂ, ਮਲਟੀ-ਵਿੰਡੋ ਲਈ ਸਾਰੀਆਂ ਸਰਗਰਮੀਆਂ ਨੂੰ ਆਕਾਰ ਬਦਲਣਯੋਗ ਬਣਾਓ।"</string> <string name="enable_freeform_support" msgid="7599125687603914253">"ਫ੍ਰੀਫਾਰਮ ਵਿੰਡੋਜ਼ ਨੂੰ ਚਾਲੂ ਕਰੋ"</string> <string name="enable_freeform_support_summary" msgid="1822862728719276331">"ਪ੍ਰਯੋਗਮਈ ਫ੍ਰੀਫਾਰਮ ਵਿੰਡੋਜ਼ ਲਈ ਸਮਰਥਨ ਨੂੰ ਚਾਲੂ ਕਰੋ।"</string> @@ -436,7 +436,7 @@ <string name="transcode_notification" msgid="5560515979793436168">"ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਸੂਚਨਾਵਾਂ ਦਿਖਾਓ"</string> <string name="transcode_disable_cache" msgid="3160069309377467045">"ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਕੈਸ਼ੇ ਬੰਦ ਕਰੋ"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"ਚੱਲ ਰਹੀਆਂ ਸੇਵਾਵਾਂ"</string> - <string name="runningservices_settings_summary" msgid="1046080643262665743">"ਇਸ ਵੇਲੇ ਚੱਲ ਰਹੀਆਂ ਸੇਵਾਵਾਂ ਦੇਖੋ ਅਤੇ ਇਹਨਾਂ ਨੂੰ ਕੰਟਰੋਲ ਕਰੋ"</string> + <string name="runningservices_settings_summary" msgid="1046080643262665743">"ਇਸ ਵੇਲੇ ਚੱਲ ਰਹੀਆਂ ਸੇਵਾਵਾਂ ਦੇਖੋ ਅਤੇ ਉਨ੍ਹਾਂ ਨੂੰ ਕੰਟਰੋਲ ਕਰੋ"</string> <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ਅਮਲੀਕਰਨ"</string> <string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView ਅਮਲੀਕਰਨ ਸੈੱਟ ਕਰੋ"</string> <string name="select_webview_provider_toast_text" msgid="8512254949169359848">"ਇਹ ਚੋਣ ਹੁਣ ਵੈਧ ਨਹੀਂ ਹੈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> @@ -552,7 +552,7 @@ <string name="help_label" msgid="3528360748637781274">"ਮਦਦ ਅਤੇ ਵਿਚਾਰ"</string> <string name="storage_category" msgid="2287342585424631813">"ਸਟੋਰੇਜ"</string> <string name="shared_data_title" msgid="1017034836800864953">"ਸਾਂਝਾ ਕੀਤਾ ਡਾਟਾ"</string> - <string name="shared_data_summary" msgid="5516326713822885652">"ਸਾਂਝਾ ਕੀਤੇ ਡਾਟੇ ਨੂੰ ਦੇਖੋ ਅਤੇ ਸੋਧੋ"</string> + <string name="shared_data_summary" msgid="5516326713822885652">"ਸਾਂਝਾ ਕੀਤਾ ਡਾਟਾ ਦੇਖੋ ਅਤੇ ਉਸ ਨੂੰ ਸੋਧੋ"</string> <string name="shared_data_no_blobs_text" msgid="3108114670341737434">"ਇਸ ਵਰਤੋਂਕਾਰ ਲਈ ਕੋਈ ਸਾਂਝਾ ਕੀਤਾ ਡਾਟਾ ਨਹੀਂ ਹੈ।"</string> <string name="shared_data_query_failure_text" msgid="3489828881998773687">"ਸਾਂਝੇ ਕੀਤੇ ਡਾਟੇ ਨੂੰ ਪ੍ਰਾਪਤ ਕਰਨ ਵੇਲੇ ਕੋਈ ਗੜਬੜ ਹੋ ਗਈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> <string name="blob_id_text" msgid="8680078988996308061">"ਸਾਂਝਾ ਕੀਤੇ ਡਾਟੇ ਦੀ ਆਈਡੀ: <xliff:g id="BLOB_ID">%d</xliff:g>"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR ਕੋਡ ਸਕੈਨ ਕਰੋ"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"ਸੁਣਨਾ ਸ਼ੁਰੂ ਕਰਨ ਲਈ, ਹੇਠਾਂ ਦਿੱਤੇ QR ਕੋਡ ਨੂੰ ਕੇਂਦਰ ਵਿੱਚ ਰੱਖੋ"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR ਕੋਡ ਦਾ ਫਾਰਮੈਟ ਵੈਧ ਨਹੀਂ ਹੈ"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਦੇ ਪ੍ਰਸਾਰਨ ਨੂੰ ਰੋਕਣਾ ਹੈ?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"ਜੇ ਤੁਸੀਂ <xliff:g id="SWITCHAPP">%1$s</xliff:g> ਦਾ ਪ੍ਰਸਾਰਨ ਕਰਦੇ ਹੋ ਜਾਂ ਆਊਟਪੁੱਟ ਬਦਲਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਡਾ ਮੌਜੂਦਾ ਪ੍ਰਸਾਰਨ ਰੁਕ ਜਾਵੇਗਾ"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ਦਾ ਪ੍ਰਸਾਰਨ ਕਰੋ"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"ਆਊਟਪੁੱਟ ਬਦਲੋ"</string> </resources> diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml index d523148de088..aa5359af1fc2 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -389,7 +389,7 @@ <string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Warstwy debugowania GPU"</string> <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Zezwalaj na ładowanie warstw debugowania GPU"</string> <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Włącz szczegółowe rejestrowanie dostawcy"</string> - <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Dołączaj do raportów o błędach dodatkowe dane dostawcy dotyczące konkretnego urządzenia, które mogą zawierać dane prywatne oraz wykorzystywać więcej baterii lub pamięci."</string> + <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Dołączaj do raportów o błędach dodatkowe dane dostawcy dotyczące konkretnego urządzenia, które mogą zawierać dane prywatne oraz wykorzystywać więcej baterii lub pamięci"</string> <string name="window_animation_scale_title" msgid="5236381298376812508">"Skala animacji okna"</string> <string name="transition_animation_scale_title" msgid="1278477690695439337">"Skala animacji przejścia"</string> <string name="animator_duration_scale_title" msgid="7082913931326085176">"Skala długości animacji"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Skaner kodów QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Aby odsłuchać, wyśrodkuj kod QR poniżej"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"Nieprawidłowy format kodu QR"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Zatrzymaj transmisję aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Jeśli transmitujesz aplikację <xliff:g id="SWITCHAPP">%1$s</xliff:g> lub zmieniasz dane wyjściowe, Twoja obecna transmisja zostanie zakończona"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Transmisja aplikacji <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Zmień dane wyjściowe"</string> </resources> diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml index 627d7ba7ac4b..a0355b9c419e 100644 --- a/packages/SettingsLib/res/values-pt-rBR/strings.xml +++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml @@ -266,7 +266,7 @@ <string name="bugreport_in_power" msgid="8664089072534638709">"Atalho para relatório de bugs"</string> <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Mostrar um botão para gerar relatórios de bugs no menu do botão liga/desliga"</string> <string name="keep_screen_on" msgid="1187161672348797558">"Permanecer ativo"</string> - <string name="keep_screen_on_summary" msgid="1510731514101925829">"A tela nunca entrará em suspensão enquanto estiver carregando"</string> + <string name="keep_screen_on_summary" msgid="1510731514101925829">"A tela nunca entra em suspensão enquanto está carregando"</string> <string name="bt_hci_snoop_log" msgid="7291287955649081448">"Ativar registro de rastreamento Bluetooth HCI"</string> <string name="bt_hci_snoop_log_summary" msgid="6808538971394092284">"Capturar pacotes de Bluetooth. Ative o Bluetooth depois de alterar essa configuração."</string> <string name="oem_unlock_enable" msgid="5334869171871566731">"Desbloqueio de OEM"</string> @@ -282,7 +282,7 @@ <string name="wifi_scan_throttling" msgid="2985624788509913617">"Limitar busca por Wi-Fi"</string> <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"Ordem aleatória de MAC não persistente no Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8275958101875563572">"Dados móveis sempre ativos"</string> - <string name="tethering_hardware_offload" msgid="4116053719006939161">"Aceleração de hardware de tethering"</string> + <string name="tethering_hardware_offload" msgid="4116053719006939161">"Aceleração de hardware para tethering"</string> <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Mostrar dispositivos Bluetooth sem nomes"</string> <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Desativar volume absoluto"</string> <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Ativar Gabeldorsche"</string> @@ -327,7 +327,7 @@ <string name="allow_mock_location_summary" msgid="179780881081354579">"Permitir locais fictícios"</string> <string name="debug_view_attributes" msgid="3539609843984208216">"Ativar visualização de inspeção de atributo"</string> <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"Sempre manter dados móveis ativos, mesmo quando o Wi-Fi estiver ativado (para troca rápida de rede)"</string> - <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Usar aceleração de hardware de tethering quando disponível"</string> + <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Usar aceleração de hardware para tethering quando disponível"</string> <string name="adb_warning_title" msgid="7708653449506485728">"Permitir a depuração USB?"</string> <string name="adb_warning_message" msgid="8145270656419669221">"A depuração USB serve apenas para fins de desenvolvimento. Use-a para copiar dados entre o computador e o dispositivo, instalar apps no seu aparelho sem notificação e ler dados de registro."</string> <string name="adbwifi_warning_title" msgid="727104571653031865">"Permitir a depuração por Wi-Fi?"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Ler o código QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Para começar a ouvir, centralize o código QR abaixo"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"O código QR não está em um formato válido"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Interromper a transmissão do app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Se você transmitir o app <xliff:g id="SWITCHAPP">%1$s</xliff:g> ou mudar a saída, a transmissão atual será interrompida"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Transmitir <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Mudar saída"</string> </resources> diff --git a/packages/SettingsLib/res/values-pt-rPT/arrays.xml b/packages/SettingsLib/res/values-pt-rPT/arrays.xml index 6ae02a556eea..3e7ee052ba1c 100644 --- a/packages/SettingsLib/res/values-pt-rPT/arrays.xml +++ b/packages/SettingsLib/res/values-pt-rPT/arrays.xml @@ -56,7 +56,7 @@ <string-array name="hdcp_checking_summaries"> <item msgid="4045840870658484038">"Nunca utilizar a verificação HDCP"</item> <item msgid="8254225038262324761">"Utilizar a verificação HDCP para conteúdo DRM apenas"</item> - <item msgid="6421717003037072581">"Utilizar sempre a verificação HDCP"</item> + <item msgid="6421717003037072581">"Usar sempre a verificação HDCP"</item> </string-array> <string-array name="bt_hci_snoop_log_entries"> <item msgid="695678520785580527">"Desativado"</item> diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index 98d65f5c6a5b..5b4172536a1f 100644 --- a/packages/SettingsLib/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml @@ -335,7 +335,7 @@ <string name="adb_keys_warning_message" msgid="2968555274488101220">"Revogar acesso à depuração USB de todos os computadores anteriormente autorizados?"</string> <string name="dev_settings_warning_title" msgid="8251234890169074553">"Permitir definições de programação?"</string> <string name="dev_settings_warning_message" msgid="37741686486073668">"Estas definições destinam-se apenas a programação. Podem fazer com que o seu aparelho e as aplicações nele existentes falhem ou funcionem mal."</string> - <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"Verificar aplicações de USB"</string> + <string name="verify_apps_over_usb_title" msgid="6031809675604442636">"Verificar apps por USB"</string> <string name="verify_apps_over_usb_summary" msgid="1317933737581167839">"Verificar as aplicações instaladas via ADB/ADT para detetar comportamento perigoso"</string> <string name="bluetooth_show_devices_without_names_summary" msgid="780964354377854507">"São apresentados os dispositivos Bluetooth sem nomes (apenas endereços MAC)"</string> <string name="bluetooth_disable_absolute_volume_summary" msgid="2006309932135547681">"Desativa a funcionalidade de volume absoluto do Bluetooth caso existam problemas de volume com dispositivos remotos, como um volume insuportavelmente alto ou a ausência de controlo"</string> @@ -372,7 +372,7 @@ <string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"Piscar camadas de hardware em verde ao atualizar"</string> <string name="debug_hw_overdraw" msgid="8944851091008756796">"Depurar sobreposição GPU"</string> <string name="disable_overlays" msgid="4206590799671557143">"Desativar sobreposições HW"</string> - <string name="disable_overlays_summary" msgid="1954852414363338166">"Utilizar sempre GPU para a composição do ecrã"</string> + <string name="disable_overlays_summary" msgid="1954852414363338166">"Usar sempre GPU para a composição do ecrã"</string> <string name="simulate_color_space" msgid="1206503300335835151">"Simular espaço da cor"</string> <string name="enable_opengl_traces_title" msgid="4638773318659125196">"Ativar vestígios OpenGL"</string> <string name="usb_audio_disable_routing" msgid="3367656923544254975">"Desativar encaminhamento áudio USB"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Leia o código QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Para começar a ouvir, centre o código QR abaixo"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"O código QR não é um formato válido"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Interromper a transmissão da app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Se transmitir a app <xliff:g id="SWITCHAPP">%1$s</xliff:g> ou alterar a saída, a sua transmissão atual é interrompida"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Transmita a app <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Altere a saída"</string> </resources> diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml index 627d7ba7ac4b..a0355b9c419e 100644 --- a/packages/SettingsLib/res/values-pt/strings.xml +++ b/packages/SettingsLib/res/values-pt/strings.xml @@ -266,7 +266,7 @@ <string name="bugreport_in_power" msgid="8664089072534638709">"Atalho para relatório de bugs"</string> <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Mostrar um botão para gerar relatórios de bugs no menu do botão liga/desliga"</string> <string name="keep_screen_on" msgid="1187161672348797558">"Permanecer ativo"</string> - <string name="keep_screen_on_summary" msgid="1510731514101925829">"A tela nunca entrará em suspensão enquanto estiver carregando"</string> + <string name="keep_screen_on_summary" msgid="1510731514101925829">"A tela nunca entra em suspensão enquanto está carregando"</string> <string name="bt_hci_snoop_log" msgid="7291287955649081448">"Ativar registro de rastreamento Bluetooth HCI"</string> <string name="bt_hci_snoop_log_summary" msgid="6808538971394092284">"Capturar pacotes de Bluetooth. Ative o Bluetooth depois de alterar essa configuração."</string> <string name="oem_unlock_enable" msgid="5334869171871566731">"Desbloqueio de OEM"</string> @@ -282,7 +282,7 @@ <string name="wifi_scan_throttling" msgid="2985624788509913617">"Limitar busca por Wi-Fi"</string> <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"Ordem aleatória de MAC não persistente no Wi-Fi"</string> <string name="mobile_data_always_on" msgid="8275958101875563572">"Dados móveis sempre ativos"</string> - <string name="tethering_hardware_offload" msgid="4116053719006939161">"Aceleração de hardware de tethering"</string> + <string name="tethering_hardware_offload" msgid="4116053719006939161">"Aceleração de hardware para tethering"</string> <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Mostrar dispositivos Bluetooth sem nomes"</string> <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Desativar volume absoluto"</string> <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Ativar Gabeldorsche"</string> @@ -327,7 +327,7 @@ <string name="allow_mock_location_summary" msgid="179780881081354579">"Permitir locais fictícios"</string> <string name="debug_view_attributes" msgid="3539609843984208216">"Ativar visualização de inspeção de atributo"</string> <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"Sempre manter dados móveis ativos, mesmo quando o Wi-Fi estiver ativado (para troca rápida de rede)"</string> - <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Usar aceleração de hardware de tethering quando disponível"</string> + <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Usar aceleração de hardware para tethering quando disponível"</string> <string name="adb_warning_title" msgid="7708653449506485728">"Permitir a depuração USB?"</string> <string name="adb_warning_message" msgid="8145270656419669221">"A depuração USB serve apenas para fins de desenvolvimento. Use-a para copiar dados entre o computador e o dispositivo, instalar apps no seu aparelho sem notificação e ler dados de registro."</string> <string name="adbwifi_warning_title" msgid="727104571653031865">"Permitir a depuração por Wi-Fi?"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Ler o código QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Para começar a ouvir, centralize o código QR abaixo"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"O código QR não está em um formato válido"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Interromper a transmissão do app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Se você transmitir o app <xliff:g id="SWITCHAPP">%1$s</xliff:g> ou mudar a saída, a transmissão atual será interrompida"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Transmitir <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Mudar saída"</string> </resources> diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml index c38bd788395a..9c7a2ce0dce6 100644 --- a/packages/SettingsLib/res/values-ro/strings.xml +++ b/packages/SettingsLib/res/values-ro/strings.xml @@ -403,7 +403,7 @@ <string name="show_notification_channel_warnings" msgid="3448282400127597331">"Afișați avertismentele de pe canalul de notificări"</string> <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"Afișați avertisment pe ecran când o aplicație postează o notificare fără canal valid"</string> <string name="force_allow_on_external" msgid="9187902444231637880">"Forțați accesul aplicațiilor la stocarea externă"</string> - <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Faceți ca orice aplicație eligibilă să fie scrisă în stocarea externă, indiferent de valorile manifestului"</string> + <string name="force_allow_on_external_summary" msgid="8525425782530728238">"Permiteți scrierea oricărei aplicații eligibile în stocarea externă, indiferent de valorile manifestului"</string> <string name="force_resizable_activities" msgid="7143612144399959606">"Forțați redimensionarea activităților"</string> <string name="force_resizable_activities_summary" msgid="2490382056981583062">"Permiteți redimensionarea tuturor activităților pentru modul cu ferestre multiple, indiferent de valorile manifestului."</string> <string name="enable_freeform_support" msgid="7599125687603914253">"Activați ferestrele cu formă liberă"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Scanați codul QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Pentru a începe să ascultați, centrați codul QR de mai jos"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"Codul QR nu are un format valid"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Opriți difuzarea <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Dacă difuzați <xliff:g id="SWITCHAPP">%1$s</xliff:g> sau schimbați rezultatul, difuzarea actuală se va opri"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Difuzați <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Schimbați rezultatul"</string> </resources> diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml index 2d7ed111d8ac..3ce46e7bd0c1 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -233,10 +233,10 @@ <string name="tethering_settings_not_available" msgid="266821736434699780">"Этот пользователь не может изменять настройки режима модема"</string> <string name="apn_settings_not_available" msgid="1147111671403342300">"Этот пользователь не может изменять настройки точки доступа"</string> <string name="enable_adb" msgid="8072776357237289039">"Отладка по USB"</string> - <string name="enable_adb_summary" msgid="3711526030096574316">"Включить режим отладки при подключении к компьютеру по USB"</string> - <string name="clear_adb_keys" msgid="3010148733140369917">"Отозвать доступ для USB-отладки"</string> + <string name="enable_adb_summary" msgid="3711526030096574316">"Режим отладки при подключении по USB"</string> + <string name="clear_adb_keys" msgid="3010148733140369917">"Отозвать доступ для отладки по USB"</string> <string name="enable_adb_wireless" msgid="6973226350963971018">"Отладка по Wi-Fi"</string> - <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Режим отладки при подключении к сети Wi‑Fi"</string> + <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Режим отладки при подключении по Wi‑Fi"</string> <string name="adb_wireless_error" msgid="721958772149779856">"Ошибка"</string> <string name="adb_wireless_settings" msgid="2295017847215680229">"Отладка по Wi-Fi"</string> <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Чтобы увидеть и использовать доступные устройства, включите отладку по Wi-Fi."</string> @@ -281,7 +281,7 @@ <string name="wifi_verbose_logging" msgid="1785910450009679371">"Подробный журнал Wi‑Fi"</string> <string name="wifi_scan_throttling" msgid="2985624788509913617">"Ограничивать поиск сетей Wi‑Fi"</string> <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"Случайные MAC-адреса в сети Wi-Fi"</string> - <string name="mobile_data_always_on" msgid="8275958101875563572">"Не отключать мобильный Интернет"</string> + <string name="mobile_data_always_on" msgid="8275958101875563572">"Не отключать мобильный интернет"</string> <string name="tethering_hardware_offload" msgid="4116053719006939161">"Аппаратное ускорение в режиме модема"</string> <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Показывать Bluetooth-устройства без названий"</string> <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"Отключить абсолютный уровень громкости"</string> @@ -312,7 +312,7 @@ <string name="wifi_display_certification_summary" msgid="8111151348106907513">"Показывать параметры сертификации беспроводных мониторов"</string> <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Вести подробный журнал, показывать RSSI для каждого SSID при выборе сети"</string> <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"Уменьшает расход заряда батареи и улучшает работу сети"</string> - <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Если этот режим активирован, MAC-адрес устройства может меняться при каждом подключении к сети, в которой возможно создание случайных MAC-адресов."</string> + <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"Если этот режим активирован, MAC-адрес устройства может меняться при каждом подключении к сети, в которой возможно создание случайных MAC-адресов"</string> <string name="wifi_metered_label" msgid="8737187690304098638">"Сеть с тарификацией трафика"</string> <string name="wifi_unmetered_label" msgid="6174142840934095093">"Сеть без тарификации трафика"</string> <string name="select_logd_size_title" msgid="1604578195914595173">"Размер буфера журнала"</string> @@ -380,7 +380,7 @@ <string name="debug_layout" msgid="1659216803043339741">"Показывать границы элементов"</string> <string name="debug_layout_summary" msgid="8825829038287321978">"Показывать границы обрезки, поля и т. п."</string> <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Отразить интерфейс"</string> - <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Принудительно расположить элементы интерфейса справа налево во всех локалях"</string> + <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Принудительно расположить элементы интерфейса справа налево вне зависимости от региональных настроек"</string> <string name="window_blurs" msgid="6831008984828425106">"Размытие на уровне окон"</string> <string name="force_msaa" msgid="4081288296137775550">"Включить 4x MSAA"</string> <string name="force_msaa_summary" msgid="9070437493586769500">"Включить 4x MSAA в приложениях OpenGL ES 2.0"</string> @@ -448,7 +448,7 @@ <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалия (красный/зеленый)"</string> <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалия (синий/желтый)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Коррекция цвета"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Коррекция цвета поможет вам:<br/> <ol> <li>&nbsp;Добиться нужной цветопередачи.</li> <li>&nbsp;Убрать цвета, которые мешают сосредоточиться.</li> </ol>"</string> + <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_remaining_duration_only" msgid="8264199158671531431">"Заряда хватит примерно на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -553,7 +553,7 @@ <string name="storage_category" msgid="2287342585424631813">"Хранилище"</string> <string name="shared_data_title" msgid="1017034836800864953">"Общие данные"</string> <string name="shared_data_summary" msgid="5516326713822885652">"Просмотр и изменение общих данных"</string> - <string name="shared_data_no_blobs_text" msgid="3108114670341737434">"Нет общих данных для этого пользователя."</string> + <string name="shared_data_no_blobs_text" msgid="3108114670341737434">"Для этого пользователя нет общих данных"</string> <string name="shared_data_query_failure_text" msgid="3489828881998773687">"При получении общих данных произошла ошибка. Повторите попытку."</string> <string name="blob_id_text" msgid="8680078988996308061">"Идентификатор общих данных: <xliff:g id="BLOB_ID">%d</xliff:g>"</string> <string name="blob_expires_text" msgid="7882727111491739331">"Срок действия истекает <xliff:g id="DATE">%s</xliff:g>"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Сканирование QR-кода"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Чтобы прослушать, поместите QR-код в центр"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"Недопустимый формат QR-кода"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Остановить трансляцию \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Если вы начнете транслировать \"<xliff:g id="SWITCHAPP">%1$s</xliff:g>\" или смените целевое устройство, текущая трансляция прервется."</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Транслировать \"<xliff:g id="SWITCHAPP">%1$s</xliff:g>\""</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Транслировать на другое устройство"</string> </resources> diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml index 7477e52a8833..0cb9c840ee12 100644 --- a/packages/SettingsLib/res/values-si/strings.xml +++ b/packages/SettingsLib/res/values-si/strings.xml @@ -47,7 +47,7 @@ <string name="wifi_security_sae" msgid="3644520541721422843">"WPA3-Personal"</string> <string name="wifi_security_psk_sae" msgid="8135104122179904684">"WPA2/WPA3-Personal"</string> <string name="wifi_security_none_owe" msgid="5241745828327404101">"නැත/වැඩි දියුණු කළ විවෘත"</string> - <string name="wifi_security_owe" msgid="3343421403561657809">"වැඩි දියුණු කළ විවෘත"</string> + <string name="wifi_security_owe" msgid="3343421403561657809">"Enhanced Open"</string> <string name="wifi_security_eap_suiteb" msgid="415842785991698142">"WPA3-Enterprise බිටු-192"</string> <string name="wifi_remembered" msgid="3266709779723179188">"සුරකින ලදි"</string> <string name="wifi_disconnected" msgid="7054450256284661757">"විසන්ධි විය"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR කේතය ස්කෑන් කරන්න"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"සවන් දීම ආරම්භ කිරීමට, පහත QR කේතය මධ්යගත කරන්න"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR කේතය වලංගු ආකෘතියක් නොවේ"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> විකාශනය කිරීම නවත්වන්නද?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"ඔබ <xliff:g id="SWITCHAPP">%1$s</xliff:g> විකාශනය කළහොත් හෝ ප්රතිදානය වෙනස් කළහොත්, ඔබගේ වත්මන් විකාශනය නවතිනු ඇත."</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> විකාශනය"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"ප්රතිදානය වෙනස් කරන්න"</string> </resources> diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml index d5dd6c534c67..72a9f40ff5a6 100644 --- a/packages/SettingsLib/res/values-sk/strings.xml +++ b/packages/SettingsLib/res/values-sk/strings.xml @@ -173,9 +173,9 @@ <string name="data_usage_uninstalled_apps" msgid="1933665711856171491">"Odstránené aplikácie"</string> <string name="data_usage_uninstalled_apps_users" msgid="5533981546921913295">"Odstránené aplikácie a používatelia"</string> <string name="data_usage_ota" msgid="7984667793701597001">"Aktualizácie systému"</string> - <string name="tether_settings_title_usb" msgid="3728686573430917722">"Pripojenie cez USB"</string> + <string name="tether_settings_title_usb" msgid="3728686573430917722">"Tethering cez USB"</string> <string name="tether_settings_title_wifi" msgid="4803402057533895526">"Prenosný prístupový bod"</string> - <string name="tether_settings_title_bluetooth" msgid="916519902721399656">"Pripojenie cez Bluetooth"</string> + <string name="tether_settings_title_bluetooth" msgid="916519902721399656">"Tethering cez Bluetooth"</string> <string name="tether_settings_title_usb_bluetooth" msgid="1727111807207577322">"Zdieľané pripojenie"</string> <string name="tether_settings_title_all" msgid="8910259483383010470">"Zdieľané pripojenie a prenosný hotspot"</string> <string name="managed_user_title" msgid="449081789742645723">"Všetky pracovné aplikácie"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Naskenovanie QR kódu"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Ak chcete začať počúvať, umiestnite QR kód do stredu nižšie"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR kód nie je platný formát"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Chcete zastaviť vysielanie aplikácie <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Ak vysielate aplikáciu <xliff:g id="SWITCHAPP">%1$s</xliff:g> alebo zmeníte výstup, aktuálne vysielanie bude zastavené"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Vysielanie aplikácie <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Zmena výstupu"</string> </resources> diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml index a609ab83a049..e49f0c4e5e02 100644 --- a/packages/SettingsLib/res/values-sl/strings.xml +++ b/packages/SettingsLib/res/values-sl/strings.xml @@ -376,7 +376,7 @@ <string name="simulate_color_space" msgid="1206503300335835151">"Simul. barvnega prostora"</string> <string name="enable_opengl_traces_title" msgid="4638773318659125196">"Omogoči sledi OpenGL"</string> <string name="usb_audio_disable_routing" msgid="3367656923544254975">"Onem. usmerjanje zvoka prek USB"</string> - <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"Onem. samod. usmerjanja na zun. zvoč. naprave USB."</string> + <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"Onem. samod. usmerjanje na zun. zvoč. naprave USB."</string> <string name="debug_layout" msgid="1659216803043339741">"Prikaži meje postavitve"</string> <string name="debug_layout_summary" msgid="8825829038287321978">"Pokaži meje obrezovanja, obrobe ipd."</string> <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Vsili od desne proti levi"</string> @@ -393,7 +393,7 @@ <string name="window_animation_scale_title" msgid="5236381298376812508">"Merilo animacije okna"</string> <string name="transition_animation_scale_title" msgid="1278477690695439337">"Merilo animacije prehoda"</string> <string name="animator_duration_scale_title" msgid="7082913931326085176">"Merilo trajanja animacije"</string> - <string name="overlay_display_devices_title" msgid="5411894622334469607">"Simul. sekund. prikazov."</string> + <string name="overlay_display_devices_title" msgid="5411894622334469607">"Simuliraj sekundarne zaslone"</string> <string name="debug_applications_category" msgid="5394089406638954196">"Aplikacije"</string> <string name="immediately_destroy_activities" msgid="1826287490705167403">"Ne obdrži dejavnosti"</string> <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"Uniči vsako dejavnost, ko uporabnik preneha z njo."</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Optično branje kode QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Če želite začeti poslušati, postavite spodnjo kodo QR na sredino."</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"Koda QR nima pravilne oblike zapisa."</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Želite ustaviti oddajanje aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Če oddajate aplikacijo <xliff:g id="SWITCHAPP">%1$s</xliff:g> ali spremenite izhod, bo trenutno oddajanje ustavljeno."</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Oddajaj aplikacijo <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Sprememba izhoda"</string> </resources> diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml index 25f3b978049c..9b62de269bb9 100644 --- a/packages/SettingsLib/res/values-sq/strings.xml +++ b/packages/SettingsLib/res/values-sq/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Skano kodin QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Që të fillosh të dëgjosh, vendos në qendër kodin QR më poshtë"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"Kodi QR nuk është në format të vlefshëm"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Të ndalohet transmetimi i <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Nëse transmeton <xliff:g id="SWITCHAPP">%1$s</xliff:g> ose ndryshon daljen, transmetimi yt aktual do të ndalojë"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Transmeto <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Ndrysho daljen"</string> </resources> diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml index 0e2f0d0d14a3..eba79105f437 100644 --- a/packages/SettingsLib/res/values-sr/strings.xml +++ b/packages/SettingsLib/res/values-sr/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Скенирајте QR кôд"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Да бисте почели да слушате, центрирајте QR кôд испод"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR кôд није у важећем формату"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Желите да зауставите емитовање апликације <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Ако емитујете апликацију <xliff:g id="SWITCHAPP">%1$s</xliff:g> или промените излаз, актуелно емитовање ће се зауставити"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Емитујте апликацију <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Промените излаз"</string> </resources> diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml index 430dd4543d45..1c1c38fc193b 100644 --- a/packages/SettingsLib/res/values-sv/strings.xml +++ b/packages/SettingsLib/res/values-sv/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Skanna QR-kod"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Centrera QR-koden nedan om du vill börja lyssna"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR-kodens format är ogiltigt"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Vill du sluta sända från <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Om en utsändning från <xliff:g id="SWITCHAPP">%1$s</xliff:g> pågår eller om du byter ljudutgång avbryts den nuvarande utsändningen"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Sänd från <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Byt ljudutgång"</string> </resources> diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml index 79d9532e0be0..fd7c893f0998 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Changanua msimbo wa QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Ili uanze kusikiliza, weka katikati msimbo wa QR ulio hapa chini"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"Msimbo wa QR si muundo sahihi"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Ungependa kusimamisha utangazaji kwenye <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Ikiwa unatangaza kwenye <xliff:g id="SWITCHAPP">%1$s</xliff:g> au unabadilisha maudhui, tangazo lako la sasa litasimamishwa"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Tangaza kwenye <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Badilisha maudhui"</string> </resources> diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml index 9a5d1eebbfe2..236b74bfcb57 100644 --- a/packages/SettingsLib/res/values-ta/strings.xml +++ b/packages/SettingsLib/res/values-ta/strings.xml @@ -190,7 +190,7 @@ <string name="tts_default_pitch_title" msgid="6988592215554485479">"ஒலித்திறன்"</string> <string name="tts_default_pitch_summary" msgid="9132719475281551884">"உருவாக்கப்படும் பேச்சின் டோன் பாதிக்கப்படும்"</string> <string name="tts_default_lang_title" msgid="4698933575028098940">"மொழி"</string> - <string name="tts_lang_use_system" msgid="6312945299804012406">"அமைப்பின் மொழியைப் பயன்படுத்தவும்"</string> + <string name="tts_lang_use_system" msgid="6312945299804012406">"சாதனத்தின் மொழியைப் பயன்படுத்தவும்"</string> <string name="tts_lang_not_selected" msgid="7927823081096056147">"மொழி தேர்ந்தெடுக்கப்படவில்லை"</string> <string name="tts_default_lang_summary" msgid="9042620014800063470">"பேசப்படும் உரைக்கு மொழி சார்ந்த குரலை அமைக்கிறது"</string> <string name="tts_play_example_title" msgid="1599468547216481684">"எடுத்துக்காட்டைக் கவனிக்கவும்"</string> @@ -233,7 +233,7 @@ <string name="tethering_settings_not_available" msgid="266821736434699780">"இவரால் இணைப்புமுறை அமைப்புகளை மாற்ற முடியாது"</string> <string name="apn_settings_not_available" msgid="1147111671403342300">"இவரால் ஆக்சஸ் பாயிண்ட் நேம் அமைப்புகளை மாற்ற முடியாது"</string> <string name="enable_adb" msgid="8072776357237289039">"USB பிழைதிருத்தம்"</string> - <string name="enable_adb_summary" msgid="3711526030096574316">"USB இணைக்கப்பட்டிருக்கும்போது பிழைத்திருத்தப் பயன்முறையை அமை"</string> + <string name="enable_adb_summary" msgid="3711526030096574316">"USB இணைக்கப்பட்டிருக்கும்போது பிழைத்திருத்தப் பயன்முறை இயக்கப்படும்"</string> <string name="clear_adb_keys" msgid="3010148733140369917">"USB பிழைத்திருத்த அங்கீகரிப்புகளை நிராகரி"</string> <string name="enable_adb_wireless" msgid="6973226350963971018">"வைஃபை பிழைதிருத்தம்"</string> <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"வைஃபையை இணைக்கும்போது பிழைதிருத்தப் பயன்முறை இயக்கப்படும்"</string> @@ -309,8 +309,8 @@ <string name="private_dns_mode_provider" msgid="3619040641762557028">"தனிப்பட்ட DNS வழங்குநரின் ஹோஸ்ட் பெயர்"</string> <string name="private_dns_mode_provider_hostname_hint" msgid="6564868953748514595">"DNS வழங்குநரின் ஹோஸ்ட் பெயரை உள்ளிடவும்"</string> <string name="private_dns_mode_provider_failure" msgid="8356259467861515108">"இணைக்க முடியவில்லை"</string> - <string name="wifi_display_certification_summary" msgid="8111151348106907513">"வயர்லெஸ் காட்சி சான்றுக்கான விருப்பங்களைக் காட்டு"</string> - <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"வைஃபை நுழைவு அளவை அதிகரித்து, வைஃபை தேர்வுக் கருவியில் ஒவ்வொன்றிற்கும் SSID RSSI ஐ காட்டுக"</string> + <string name="wifi_display_certification_summary" msgid="8111151348106907513">"வயர்லெஸ் காட்சி சான்றுக்கான விருப்பங்களைக் காட்டும்"</string> + <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"வைஃபை நுழைவு அளவை அதிகரித்து, வைஃபை தேர்வுக் கருவியில் ஒவ்வொன்றிற்கும் SSID RSSI ஐ காட்டும்"</string> <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"பேட்டரி தீர்ந்துபோவதைக் குறைத்து நெட்வொர்க்கின் செயல்திறனை மேம்படுத்தும்"</string> <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"இந்தப் பயன்முறை இயக்கப்பட்டிருக்கும்போது இந்தச் சாதனத்தின் MAC முகவரி ஒவ்வொரு முறை \'MAC முகவரியை ரேண்டம் ஆக்குதல்\' இயக்கப்பட்டிருக்கும் நெட்வொர்க்குடன் இணைக்கப்படும்போதும் மாறக்கூடும்."</string> <string name="wifi_metered_label" msgid="8737187690304098638">"கட்டண நெட்வொர்க்"</string> @@ -347,7 +347,7 @@ <string name="hdcp_checking_dialog_title" msgid="7691060297616217781">"HDCP சரிபார்க்கும் செயல்பாடுகளை அமை"</string> <string name="debug_debugging_category" msgid="535341063709248842">"பிழைதிருத்தம்"</string> <string name="debug_app" msgid="8903350241392391766">"பிழைத்திருத்தப் பயன்பாட்டைத் தேர்ந்தெடுக்கவும்"</string> - <string name="debug_app_not_set" msgid="1934083001283807188">"பிழைத்திருத்தப் ஆப்ஸ் அமைக்கப்படவில்லை"</string> + <string name="debug_app_not_set" msgid="1934083001283807188">"பிழைத்திருத்த ஆப்ஸ் அமைக்கப்படவில்லை"</string> <string name="debug_app_set" msgid="6599535090477753651">"பிழைதிருத்தும் ஆப்ஸ்: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="select_application" msgid="2543228890535466325">"பயன்பாட்டைத் தேர்ந்தெடுக்கவும்"</string> <string name="no_application" msgid="9038334538870247690">"ஒன்றுமில்லை"</string> @@ -359,28 +359,28 @@ <string name="media_category" msgid="8122076702526144053">"மீடியா"</string> <string name="debug_monitoring_category" msgid="1597387133765424994">"கண்காணி"</string> <string name="strict_mode" msgid="889864762140862437">"நிலையான பயன்முறை இயக்கப்பட்டது"</string> - <string name="strict_mode_summary" msgid="1838248687233554654">"முக்கியத் தொடரிழையில் நீண்ட நேரம் செயல்படும்போது திரையைக் காட்சிப்படுத்து"</string> + <string name="strict_mode_summary" msgid="1838248687233554654">"முக்கியத் தொடரிழையில் நீண்ட நேரம் செயல்படும்போது திரையைக் காட்சிப்படுத்தும்"</string> <string name="pointer_location" msgid="7516929526199520173">"குறிப்பான் இடம்"</string> <string name="pointer_location_summary" msgid="957120116989798464">"திரையின் மேல் அடுக்கானது தற்போது தொடப்பட்டிருக்கும் தரவைக் காண்பிக்கிறது"</string> <string name="show_touches" msgid="8437666942161289025">"தட்டல்களைக் காட்டு"</string> - <string name="show_touches_summary" msgid="3692861665994502193">"தட்டல்களின் போது காட்சி அறிகுறிகளைக் காட்டு"</string> + <string name="show_touches_summary" msgid="3692861665994502193">"தட்டல்களின் போது காட்சி அறிகுறிகளைக் காட்டும்"</string> <string name="show_screen_updates" msgid="2078782895825535494">"மேலோட்ட புதுப்பிப்புகளைக் காட்டு"</string> - <string name="show_screen_updates_summary" msgid="2126932969682087406">"சாளரத்தின் பரப்புநிலைகள் புதுப்பிக்கப்படும்போது, அவற்றை முழுவதுமாகக் காட்டு"</string> + <string name="show_screen_updates_summary" msgid="2126932969682087406">"சாளரத்தின் பரப்புநிலைகள் புதுப்பிக்கப்படும்போது, அவற்றை முழுவதுமாகக் காட்டும்"</string> <string name="show_hw_screen_updates" msgid="2021286231267747506">"வியூ அப்டேட்ஸைக் காட்டு"</string> - <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"வரையும்போது, சாளரங்களில் காட்சிகளைக் காட்டு"</string> + <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="show_hw_layers_updates_summary" msgid="5850955890493054618">"வன்பொருள் லேயர்களைப் புதுப்பிக்கும்போது, அவற்றைப் பச்சை நிறத்தில் காட்டும்"</string> <string name="debug_hw_overdraw" msgid="8944851091008756796">"GPU ஓவர்டிரா பிழைதிருத்து"</string> <string name="disable_overlays" msgid="4206590799671557143">"HW மேலடுக்குகளை முடக்கு"</string> <string name="disable_overlays_summary" msgid="1954852414363338166">"திரைத் தொகுத்தலுக்கு எப்போதும் GPU ஐப் பயன்படுத்து"</string> <string name="simulate_color_space" msgid="1206503300335835151">"வண்ணத்தின் இடைவெளியை உருவகப்படுத்து"</string> <string name="enable_opengl_traces_title" msgid="4638773318659125196">"OpenGL தடயங்களை இயக்கு"</string> <string name="usb_audio_disable_routing" msgid="3367656923544254975">"USB ஆடியோ ரூட்டிங்கை முடக்கு"</string> - <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"USB ஆடியோ உபகரணத்திற்கு தன்னியக்க ரூட்டிங்கை முடக்கு"</string> + <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"USB ஆடியோ உபகரணத்திற்கு தன்னியக்க ரூட்டிங்கை முடக்கும்"</string> <string name="debug_layout" msgid="1659216803043339741">"தளவமைப்பு எல்லைகளைக் காட்டு"</string> <string name="debug_layout_summary" msgid="8825829038287321978">"கிளிப் எல்லைகள், ஓரங்கள், மேலும் பலவற்றைக் காட்டு"</string> <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL தளவமைப்பின் திசையை வலியுறுத்து"</string> - <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"எல்லா மொழிகளுக்கும் திரையின் தளவமைப்பு திசையை RTL க்கு மாற்று"</string> + <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"எல்லா மொழிகளுக்கும் திரையின் தளவமைப்பு திசையை RTL க்கு மாற்றும்"</string> <string name="window_blurs" msgid="6831008984828425106">"திரை-நிலை மங்கலை அனுமதி"</string> <string name="force_msaa" msgid="4081288296137775550">"4x MSAA ஐ வலியுறுத்து"</string> <string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 பயன்பாடுகளில் 4x MSAA ஐ இயக்கு"</string> @@ -396,7 +396,7 @@ <string name="overlay_display_devices_title" msgid="5411894622334469607">"இரண்டாம்நிலைக் காட்சிகளை உருவகப்படுத்து"</string> <string name="debug_applications_category" msgid="5394089406638954196">"ஆப்ஸ்"</string> <string name="immediately_destroy_activities" msgid="1826287490705167403">"செயல்பாடுகளை வைத்திருக்காதே"</string> - <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"பயனர் வெளியேறியதும் செயல்பாடுகளை நீக்கு"</string> + <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"பயனர் வெளியேறியதும் செயல்பாடுகளை நீக்கும்"</string> <string name="app_process_limit_title" msgid="8361367869453043007">"பின்புலச் செயல்முறை வரம்பு"</string> <string name="show_all_anrs" msgid="9160563836616468726">"பின்புல ANRகளைக் காட்டு"</string> <string name="show_all_anrs_summary" msgid="8562788834431971392">"பின்புல ஆப்ஸுக்கு, ஆப்ஸ் பதிலளிக்கவில்லை என்ற செய்தியைக் காட்டும்"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR குறியீட்டை ஸ்கேன் செய்யுங்கள்"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"ஆடியோவைக் கேட்க, கீழுள்ள QR குறியீட்டை மையப்படுத்திக் காட்டுங்கள்"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR குறியீடு சரியான வடிவமைப்பில் இல்லை"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸ் ஒலிபரப்பப்படுவதை நிறுத்தவா?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"நீங்கள் <xliff:g id="SWITCHAPP">%1$s</xliff:g> ஆப்ஸை ஒலிபரப்பினாலோ அவுட்புட்டை மாற்றினாலோ உங்களின் தற்போதைய ஒலிபரப்பு நிறுத்தப்படும்"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ஆப்ஸை ஒலிபரப்பு"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"அவுட்புட்டை மாற்று"</string> </resources> diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml index bca00c222c98..52554e216436 100644 --- a/packages/SettingsLib/res/values-te/arrays.xml +++ b/packages/SettingsLib/res/values-te/arrays.xml @@ -192,7 +192,7 @@ <string-array name="window_animation_scale_entries"> <item msgid="2675263395797191850">"యానిమేషన్ ఆఫ్లో ఉంది"</item> <item msgid="5790132543372767872">"యానిమేషన్ ప్రమాణం .5x"</item> - <item msgid="2529692189302148746">"యానిమేషన్ ప్రమాణం 1x"</item> + <item msgid="2529692189302148746">"యానిమేషన్ స్కేల్ 1x"</item> <item msgid="8072785072237082286">"యానిమేషన్ ప్రమాణం 1.5x"</item> <item msgid="3531560925718232560">"యానిమేషన్ ప్రమాణం 2x"</item> <item msgid="4542853094898215187">"యానిమేషన్ ప్రమాణం 5x"</item> @@ -201,7 +201,7 @@ <string-array name="transition_animation_scale_entries"> <item msgid="3376676813923486384">"యానిమేషన్ ఆఫ్లో ఉంది"</item> <item msgid="753422683600269114">"యానిమేషన్ ప్రమాణం .5x"</item> - <item msgid="3695427132155563489">"యానిమేషన్ ప్రమాణం 1x"</item> + <item msgid="3695427132155563489">"యానిమేషన్ స్కేల్ 1x"</item> <item msgid="9032615844198098981">"యానిమేషన్ ప్రమాణం 1.5x"</item> <item msgid="8473868962499332073">"యానిమేషన్ ప్రమాణం 2x"</item> <item msgid="4403482320438668316">"యానిమేషన్ ప్రమాణం 5x"</item> @@ -210,7 +210,7 @@ <string-array name="animator_duration_scale_entries"> <item msgid="6416998593844817378">"యానిమేషన్ ఆఫ్లో ఉంది"</item> <item msgid="875345630014338616">"యానిమేషన్ ప్రమాణం .5x"</item> - <item msgid="2753729231187104962">"యానిమేషన్ ప్రమాణం 1x"</item> + <item msgid="2753729231187104962">"యానిమేషన్ స్కేల్ 1x"</item> <item msgid="1368370459723665338">"యానిమేషన్ ప్రమాణం 1.5x"</item> <item msgid="5768005350534383389">"యానిమేషన్ ప్రమాణం 2x"</item> <item msgid="3728265127284005444">"యానిమేషన్ ప్రమాణం 5x"</item> diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index 97bd52e6de83..187e1794de93 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -282,7 +282,7 @@ <string name="wifi_scan_throttling" msgid="2985624788509913617">"Wi‑Fi స్కాన్ కుదింపు"</string> <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"Wi‑Fi నిరంతరం కాని MAC ర్యాండమైజేషన్"</string> <string name="mobile_data_always_on" msgid="8275958101875563572">"మొబైల్ డేటాని ఎల్లప్పుడూ యాక్టివ్గా ఉంచు"</string> - <string name="tethering_hardware_offload" msgid="4116053719006939161">"టెథెరింగ్ హార్డ్వేర్ వేగవృద్ధి"</string> + <string name="tethering_hardware_offload" msgid="4116053719006939161">"టెథెరింగ్ హార్డ్వేర్ యాగ్జిలరేషన్"</string> <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"పేర్లు లేని బ్లూటూత్ పరికరాలు చూపించు"</string> <string name="bluetooth_disable_absolute_volume" msgid="1452342324349203434">"సంపూర్ణ వాల్యూమ్ను డిజేబుల్ చేయి"</string> <string name="bluetooth_enable_gabeldorsche" msgid="9131730396242883416">"Gabeldorscheను ఎనేబుల్ చేయి"</string> @@ -310,7 +310,7 @@ <string name="private_dns_mode_provider_hostname_hint" msgid="6564868953748514595">"DNS ప్రొవైడర్ హోస్ట్పేరును ఎంటర్ చేయండి"</string> <string name="private_dns_mode_provider_failure" msgid="8356259467861515108">"కనెక్ట్ చేయడం సాధ్యపడలేదు"</string> <string name="wifi_display_certification_summary" msgid="8111151348106907513">"వైర్లెస్ డిస్ప్లే సర్టిఫికేషన్ ఆప్షన్లను చూపు"</string> - <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Wi‑Fi ఎంపికలో SSID RSSI ప్రకారం చూపబడే Wi‑Fi లాగింగ్ స్థాయిని పెంచండి"</string> + <string name="wifi_verbose_logging_summary" msgid="4993823188807767892">"Wi‑Fi పికర్లో SSID RSSI ప్రకారం చూపబడే Wi‑Fi లాగింగ్ స్థాయిని పెంచండి"</string> <string name="wifi_scan_throttling_summary" msgid="2577105472017362814">"బ్యాటరీ శక్తి వినియోగాన్ని తగ్గించి & నెట్వర్క్ పనితీరును మెరుగుపరుస్తుంది"</string> <string name="wifi_non_persistent_mac_randomization_summary" msgid="2159794543105053930">"ఈ మోడ్ ఎనేబుల్ అయ్యాక, MAC ర్యాండమైజేషన్ను ఎనేబుల్ చేసిన నెట్వర్క్తో కనెక్ట్ అయ్యే ప్రతిసారీ ఈ పరికరం MAC అడ్రస్ను మారవచ్చు."</string> <string name="wifi_metered_label" msgid="8737187690304098638">"గణించబడుతోంది"</string> @@ -327,7 +327,7 @@ <string name="allow_mock_location_summary" msgid="179780881081354579">"డమ్మీ లొకేషన్లను అనుమతించండి"</string> <string name="debug_view_attributes" msgid="3539609843984208216">"వీక్షణ అట్రిబ్యూట్ పర్యవేక్షణను ఎనేబుల్ చేయి"</string> <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"ఎల్లప్పుడూ మొబైల్ డేటాను యాక్టివ్గా ఉంచు, Wi‑Fi యాక్టివ్గా ఉన్నా కూడా (వేగవంతమైన నెట్వర్క్ మార్పు కోసం)."</string> - <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"అందుబాటులో ఉంటే టెథెరింగ్ హార్డ్వేర్ వేగవృద్ధిని ఉపయోగించండి"</string> + <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"అందుబాటులో ఉంటే గనుక టెథెరింగ్ హార్డ్వేర్ యాగ్జిలరేషన్ను ఉపయోగించండి"</string> <string name="adb_warning_title" msgid="7708653449506485728">"USB డీబగ్గింగ్ను అనుమతించాలా?"</string> <string name="adb_warning_message" msgid="8145270656419669221">"USB డీబగ్గింగ్ అనేది అభివృద్ధి ప్రయోజనాల కోసం మాత్రమే ఉద్దేశించబడింది. మీ కంప్యూటర్ మరియు మీ పరికరం మధ్య డేటాను కాపీ చేయడానికి, నోటిఫికేషన్ లేకుండా మీ పరికరంలో యాప్లను ఇన్స్టాల్ చేయడానికి మరియు లాగ్ డేటాను చదవడానికి దీన్ని ఉపయోగించండి."</string> <string name="adbwifi_warning_title" msgid="727104571653031865">"వైర్లెస్ డీబగ్గింగ్ను అనుమతించాలా?"</string> @@ -352,20 +352,20 @@ <string name="select_application" msgid="2543228890535466325">"యాప్ను ఎంచుకోండి"</string> <string name="no_application" msgid="9038334538870247690">"ఏదీ వద్దు"</string> <string name="wait_for_debugger" msgid="7461199843335409809">"డీబగ్గర్ కోసం వేచి ఉండండి"</string> - <string name="wait_for_debugger_summary" msgid="6846330006113363286">"డీబగ్ చేయబడిన యాప్ అమలు కావడానికి ముందు జోడించాల్సిన డీబగ్గర్ కోసం వేచి ఉంటుంది"</string> + <string name="wait_for_debugger_summary" msgid="6846330006113363286">"డీబగ్ చేయబడిన యాప్, ఎగ్జిక్యూట్ కావడానికి ముందు జోడించాల్సిన డీబగ్గర్ కోసం వేచి ఉంటుంది"</string> <string name="debug_input_category" msgid="7349460906970849771">"ఇన్పుట్"</string> <string name="debug_drawing_category" msgid="5066171112313666619">"డ్రాయింగ్"</string> - <string name="debug_hw_drawing_category" msgid="5830815169336975162">"హార్డ్వేర్తో వేగవంతమైన రెండరింగ్"</string> + <string name="debug_hw_drawing_category" msgid="5830815169336975162">"హార్డ్వేర్ యాగ్జిలరేషన్ ఆధారిత రెండరింగ్"</string> <string name="media_category" msgid="8122076702526144053">"మీడియా"</string> <string name="debug_monitoring_category" msgid="1597387133765424994">"పర్యవేక్షణ"</string> <string name="strict_mode" msgid="889864762140862437">"ఖచ్చితమైన మోడ్ ప్రారంభించబడింది"</string> <string name="strict_mode_summary" msgid="1838248687233554654">"యాప్లు ప్రధాన థ్రెడ్లో సుదీర్ఘ చర్యలు చేసేటప్పుడు స్క్రీన్ను ఫ్లాష్ చేయండి"</string> <string name="pointer_location" msgid="7516929526199520173">"పాయింటర్ లొకేషన్"</string> - <string name="pointer_location_summary" msgid="957120116989798464">"ప్రస్తుత స్పర్శ డేటాను చూపుతోన్న స్క్రీన్"</string> + <string name="pointer_location_summary" msgid="957120116989798464">"ప్రస్తుత టచ్ డేటాను చూపుతోన్న స్క్రీన్"</string> <string name="show_touches" msgid="8437666942161289025">"నొక్కినవి చూపు"</string> <string name="show_touches_summary" msgid="3692861665994502193">"నొక్కినప్పుడు దృశ్యపరమైన ప్రతిస్పందన చూపు"</string> - <string name="show_screen_updates" msgid="2078782895825535494">"సర్ఫేస్ అప్డేట్లను చూపండి"</string> - <string name="show_screen_updates_summary" msgid="2126932969682087406">"పూర్తి విండో ఉపరితలాలు అప్డేట్ చేయబడినప్పుడు వాటిని ఫ్లాష్ చేయండి"</string> + <string name="show_screen_updates" msgid="2078782895825535494">"సర్ఫేస్ అప్డేట్లను చూపు"</string> + <string name="show_screen_updates_summary" msgid="2126932969682087406">"విండో సర్ఫేస్లన్నీ అప్డేట్ అయితే ఫ్లాష్ చేయి"</string> <string name="show_hw_screen_updates" msgid="2021286231267747506">"వీక్షణ అప్డేట్లను చూపు"</string> <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"గీసినప్పుడు విండోల లోపల వీక్షణలను ఫ్లాష్ చేయి"</string> <string name="show_hw_layers_updates" msgid="5268370750002509767">"హార్డ్వేర్ లేయర్ల అప్డేట్లను చూపు"</string> @@ -373,16 +373,16 @@ <string name="debug_hw_overdraw" msgid="8944851091008756796">"GPU ఓవర్డ్రాను డీబగ్ చేయండి"</string> <string name="disable_overlays" msgid="4206590799671557143">"డిజేబుల్- HW ఓవర్లేలు"</string> <string name="disable_overlays_summary" msgid="1954852414363338166">"స్క్రీన్ కంపాజిటింగ్కు ఎల్లప్పుడూ GPUని ఉపయోగించు"</string> - <string name="simulate_color_space" msgid="1206503300335835151">"వివిధ రంగులను అనుకరించు"</string> + <string name="simulate_color_space" msgid="1206503300335835151">"రంగులను సిమ్యులేట్ చేయి"</string> <string name="enable_opengl_traces_title" msgid="4638773318659125196">"OpenGL ట్రేస్లను ప్రారంభించండి"</string> <string name="usb_audio_disable_routing" msgid="3367656923544254975">"USB ఆడియో రూటింగ్ నిలిపివేయి"</string> <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"USB ఆడియో పరికరాలకు ఆటోమేటిక్ రూటింగ్ను నిలిపివేయండి"</string> - <string name="debug_layout" msgid="1659216803043339741">"లేఅవుట్ బౌండ్లు చూపు"</string> + <string name="debug_layout" msgid="1659216803043339741">"లేఅవుట్ హద్దులను చూపు"</string> <string name="debug_layout_summary" msgid="8825829038287321978">"క్లిప్ సరిహద్దులు, అంచులు మొ. చూపు"</string> <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"RTL లేఅవుట్ దిశను నిర్బంధం చేయండి"</string> <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"అన్ని లొకేల్ల కోసం RTLకి స్క్రీన్ లేఅవుట్ దిశను నిర్భందించు"</string> <string name="window_blurs" msgid="6831008984828425106">"విండో-స్థాయి బ్లర్ అనుమతించు"</string> - <string name="force_msaa" msgid="4081288296137775550">"నిర్భందం 4x MSAA"</string> + <string name="force_msaa" msgid="4081288296137775550">"4x MSAA అమలు తప్పనిసరి"</string> <string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 యాప్లలో 4x MSAAను ప్రారంభించండి"</string> <string name="show_non_rect_clip" msgid="7499758654867881817">"దీర్ఘ చతురస్రం కాని క్లిప్ చర్యలను డీబగ్ చేయండి"</string> <string name="track_frame_time" msgid="522674651937771106">"ప్రొఫైల్ HWUI రెండరింగ్"</string> @@ -390,13 +390,13 @@ <string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"డీబగ్ యాప్ల కోసం GPU డీబగ్ లేయర్లను లోడ్ చేయడాన్ని అనుమతించండి"</string> <string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"వివరణాత్మక వెండార్ లాగింగ్ను ఎనేబుల్ చేయండి"</string> <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"బగ్ రిపోర్ట్లలో అదనపు పరికర-నిర్దిష్ట వెండార్ లాగ్లను చేర్చండి, అవి ప్రైవేట్ సమాచారాన్ని కలిగి ఉండవచ్చు, మరింత బ్యాటరీని, మరియు/లేదా మరింత స్టోరేజ్ను ఉపయోగించవచ్చు."</string> - <string name="window_animation_scale_title" msgid="5236381298376812508">"విండో యానిమేషన్ ప్రమాణం"</string> - <string name="transition_animation_scale_title" msgid="1278477690695439337">"పరివర్తన యానిమేషన్ ప్రమాణం"</string> - <string name="animator_duration_scale_title" msgid="7082913931326085176">"యానిమేటర్ వ్యవధి ప్రమాణం"</string> - <string name="overlay_display_devices_title" msgid="5411894622334469607">"ప్రత్యామ్నాయ ప్రదర్శనలను అనుకరించండి"</string> + <string name="window_animation_scale_title" msgid="5236381298376812508">"విండో యానిమేషన్ స్కేల్"</string> + <string name="transition_animation_scale_title" msgid="1278477690695439337">"ట్రాన్సిషన్ యానిమేషన్ స్కేల్"</string> + <string name="animator_duration_scale_title" msgid="7082913931326085176">"యానిమేటర్ వ్యవధి స్కేల్"</string> + <string name="overlay_display_devices_title" msgid="5411894622334469607">"ఇతర డిస్ప్లేలను సిమ్యులేట్ చేయండి"</string> <string name="debug_applications_category" msgid="5394089406638954196">"యాప్లు"</string> <string name="immediately_destroy_activities" msgid="1826287490705167403">"యాక్టివిటీస్ను ఉంచవద్దు"</string> - <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"యూజర్ నిష్క్రమించాక పూర్తి యాక్టివిటీ తొలగింపు"</string> + <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"యూజర్ నిష్క్రమించాక పూర్తి యాక్టివిటీని తొలగించు"</string> <string name="app_process_limit_title" msgid="8361367869453043007">"బ్యాక్గ్రౌండ్ ప్రాసెస్ పరిమితి"</string> <string name="show_all_anrs" msgid="9160563836616468726">"బ్యాక్గ్రౌండ్ ANRలను చూపు"</string> <string name="show_all_anrs_summary" msgid="8562788834431971392">"బ్యాక్గ్రౌండ్ యాప్ల కోసం యాప్ ప్రతిస్పందించడం లేదు అనే డైలాగ్ను చూపు"</string> @@ -568,9 +568,9 @@ <string name="user_add_profile_item_summary" msgid="5418602404308968028">"మీరు మీ ఖాతా నుండి యాప్లకు మరియు కంటెంట్కు యాక్సెస్ను పరిమితం చేయవచ్చు"</string> <string name="user_add_user_item_title" msgid="2394272381086965029">"యూజర్"</string> <string name="user_add_profile_item_title" msgid="3111051717414643029">"పరిమితం చేయబడిన ప్రొఫైల్"</string> - <string name="user_add_user_title" msgid="5457079143694924885">"కొత్త వినియోగదారుని జోడించాలా?"</string> + <string name="user_add_user_title" msgid="5457079143694924885">"కొత్త యూజర్ను జోడించాలా?"</string> <string name="user_add_user_message_long" msgid="1527434966294733380">"అదనపు యూజర్లను క్రియేట్ చేయడం ద్వారా మీరు ఈ దేవైజ్ను ఇతరులతో షేర్ చేయవచ్చు. ప్రతి యూజర్కు వారికంటూ ప్రత్యేక స్థలం ఉంటుంది, వారు ఆ స్థలాన్ని యాప్లు, వాల్పేపర్ మొదలైనవాటితో అనుకూలీకరించవచ్చు. యూజర్లు ప్రతి ఒక్కరిపై ప్రభావం చూపే Wi‑Fi వంటి పరికర సెట్టింగ్లను కూడా సర్దుబాటు చేయవచ్చు.\n\nమీరు కొత్త యూజర్ ను జోడించినప్పుడు, ఆ వ్యక్తి వారికంటూ స్వంత స్థలం సెట్ చేసుకోవాలి.\n\nఏ వినియోగదారు అయినా మిగిలిన అందరు యూజర్ల కోసం యాప్లను అప్డేట్ చేయవచ్చు. యాక్సెసిబిలిటీ సెట్టింగ్లు మరియు సేవలు కొత్త యూజర్కి బదిలీ కాకపోవచ్చు."</string> - <string name="user_add_user_message_short" msgid="3295959985795716166">"మీరు కొత్త వినియోగదారుని జోడించినప్పుడు, ఆ వ్యక్తి తన స్థలాన్ని సెటప్ చేసుకోవాలి.\n\nఏ వినియోగదారు అయినా మిగతా అందరు వినియోగదారుల కోసం యాప్లను అప్డేట్ చేయగలరు."</string> + <string name="user_add_user_message_short" msgid="3295959985795716166">"మీరు కొత్త యూజర్ను = జోడించినప్పుడు, ఆ వ్యక్తి తన స్పేస్ను సెటప్ చేసుకోవాలి.\n\nఏ యూజర్ అయినా మిగతా యూజర్ల కోసం యాప్లను అప్డేట్ చేయగలరు."</string> <string name="user_setup_dialog_title" msgid="8037342066381939995">"యూజర్ను ఇప్పుడే సెటప్ చేయాలా?"</string> <string name="user_setup_dialog_message" msgid="269931619868102841">"పరికరాన్ని తీసుకోవడానికి వ్యక్తి అందుబాటులో ఉన్నారని నిర్ధారించుకొని, ఆపై వారికి నిల్వ స్థలాన్ని సెటప్ చేయండి"</string> <string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"ఇప్పుడు ప్రొఫైల్ను సెటప్ చేయాలా?"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR కోడ్ను స్కాన్ చేయండి"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"వినడం ప్రారంభించడానికి, కింద ఉన్న QR కోడ్ను మధ్యలో ఉంచండి"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR కోడ్ చెల్లుబాటు అయ్యే ఫార్మాట్లో లేదు"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> ప్రసారం చేయడాన్ని ఆపివేయాలా?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"మీరు <xliff:g id="SWITCHAPP">%1$s</xliff:g> ప్రసారం చేస్తే లేదా అవుట్పుట్ను మార్చినట్లయితే, మీ ప్రస్తుత ప్రసారం ఆగిపోతుంది"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ప్రసారం చేయండి"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"అవుట్పుట్ను మార్చండి"</string> </resources> diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml index 96b40d510897..41ef1e41b90f 100644 --- a/packages/SettingsLib/res/values-th/strings.xml +++ b/packages/SettingsLib/res/values-th/strings.xml @@ -226,9 +226,9 @@ <string name="category_personal" msgid="6236798763159385225">"ส่วนตัว"</string> <string name="category_work" msgid="4014193632325996115">"ที่ทำงาน"</string> <string name="development_settings_title" msgid="140296922921597393">"ตัวเลือกสำหรับนักพัฒนาแอป"</string> - <string name="development_settings_enable" msgid="4285094651288242183">"เปิดใช้ตัวเลือกสำหรับนักพัฒนาซอฟต์แวร์"</string> + <string name="development_settings_enable" msgid="4285094651288242183">"เปิดใช้ตัวเลือกสำหรับนักพัฒนาแอป"</string> <string name="development_settings_summary" msgid="8718917813868735095">"ตั้งค่าตัวเลือกสำหรับการพัฒนาแอปพลิเคชัน"</string> - <string name="development_settings_not_available" msgid="355070198089140951">"ตัวเลือกสำหรับนักพัฒนาซอฟต์แวร์ไม่สามารถใช้ได้สำหรับผู้ใช้นี้"</string> + <string name="development_settings_not_available" msgid="355070198089140951">"ตัวเลือกสำหรับนักพัฒนาแอปไม่สามารถใช้ได้สำหรับผู้ใช้นี้"</string> <string name="vpn_settings_not_available" msgid="2894137119965668920">"การตั้งค่า VPN ไม่สามารถใช้ได้สำหรับผู้ใช้รายนี้"</string> <string name="tethering_settings_not_available" msgid="266821736434699780">"การตั้งค่าการปล่อยสัญญาณไม่สามารถใช้ได้สำหรับผู้ใช้รายนี้"</string> <string name="apn_settings_not_available" msgid="1147111671403342300">"การตั้งค่าจุดเข้าใช้งานไม่สามารถใช้ได้สำหรับผู้ใช้รายนี้"</string> @@ -352,7 +352,7 @@ <string name="select_application" msgid="2543228890535466325">"เลือกแอปพลิเคชัน"</string> <string name="no_application" msgid="9038334538870247690">"ไม่มี"</string> <string name="wait_for_debugger" msgid="7461199843335409809">"รอโปรแกรมแก้ไขข้อบกพร่อง"</string> - <string name="wait_for_debugger_summary" msgid="6846330006113363286">"แอปพลิเคชันที่มีการแก้ปัญหาจะรอให้โปรแกรมแก้ไขข้อบกพร่องแนบข้อมูลก่อนปฏิบัติการ"</string> + <string name="wait_for_debugger_summary" msgid="6846330006113363286">"แอปพลิเคชันที่มีการแก้ไขข้อบกพร่องจะรอให้โปรแกรมแก้ไขข้อบกพร่องแนบข้อมูลก่อนปฏิบัติการ"</string> <string name="debug_input_category" msgid="7349460906970849771">"อินพุต"</string> <string name="debug_drawing_category" msgid="5066171112313666619">"การวาดภาพ"</string> <string name="debug_hw_drawing_category" msgid="5830815169336975162">"การแสดงผลที่มีการเร่งด้วยฮาร์ดแวร์"</string> @@ -379,8 +379,8 @@ <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"ปิดการกำหนดเส้นทางโดยอัตโนมัติไปยังอุปกรณ์ต่อพ่วงเสียงทาง USB"</string> <string name="debug_layout" msgid="1659216803043339741">"แสดงขอบของการจัดวาง"</string> <string name="debug_layout_summary" msgid="8825829038287321978">"แสดงหน้าปกคลิป ขอบ ฯลฯ"</string> - <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"บังคับทิศทางการจัดวาง RTL"</string> - <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"บังคับทิศทางการจัดวางหน้าจอเป็น RTL สำหรับทุกภาษา"</string> + <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"บังคับทิศทางการจัดวางขวาไปซ้าย"</string> + <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"บังคับทิศทางการจัดวางหน้าจอเป็นขวาไปซ้ายสำหรับทุกภาษา"</string> <string name="window_blurs" msgid="6831008984828425106">"อนุญาตการเบลอระดับหน้าต่าง"</string> <string name="force_msaa" msgid="4081288296137775550">"บังคับใช้ 4x MSAA"</string> <string name="force_msaa_summary" msgid="9070437493586769500">"เปิดใช้งาน 4x MSAA ในแอปพลิเคชัน OpenGL ES 2.0"</string> @@ -398,7 +398,7 @@ <string name="immediately_destroy_activities" msgid="1826287490705167403">"ไม่เก็บกิจกรรม"</string> <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"ล้างทุกกิจกรรมทันทีที่ผู้ใช้ออกไป"</string> <string name="app_process_limit_title" msgid="8361367869453043007">"ขีดจำกัดกระบวนการเบื้องหลัง"</string> - <string name="show_all_anrs" msgid="9160563836616468726">"แสดง ANR พื้นหลัง"</string> + <string name="show_all_anrs" msgid="9160563836616468726">"แสดง ANR เบื้องหลัง"</string> <string name="show_all_anrs_summary" msgid="8562788834431971392">"แสดงกล่องโต้ตอบ \"แอปไม่ตอบสนอง\" สำหรับแอปเบื้องหลัง"</string> <string name="show_notification_channel_warnings" msgid="3448282400127597331">"แสดงคำเตือนจากช่องทางการแจ้งเตือน"</string> <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"แสดงคำเตือนบนหน้าจอเมื่อแอปโพสต์การแจ้งเตือนโดยไม่มีช่องทางที่ถูกต้อง"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"สแกนคิวอาร์โค้ด"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"ถือให้คิวอาร์โค้ดอยู่กลางช่องด้านล่างเพื่อเริ่มฟัง"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"คิวอาร์โค้ดมีรูปแบบไม่ถูกต้อง"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"หยุดการออกอากาศ <xliff:g id="APP_NAME">%1$s</xliff:g> ไหม"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"หากคุณออกอากาศ <xliff:g id="SWITCHAPP">%1$s</xliff:g> หรือเปลี่ยนแปลงเอาต์พุต การออกอากาศในปัจจุบันจะหยุดลง"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"ออกอากาศ <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"เปลี่ยนเอาต์พุต"</string> </resources> diff --git a/packages/SettingsLib/res/values-tl/arrays.xml b/packages/SettingsLib/res/values-tl/arrays.xml index 4e06a6d80a30..bdd8706329cc 100644 --- a/packages/SettingsLib/res/values-tl/arrays.xml +++ b/packages/SettingsLib/res/values-tl/arrays.xml @@ -55,7 +55,7 @@ </string-array> <string-array name="hdcp_checking_summaries"> <item msgid="4045840870658484038">"Huwag kailanman gumamit ng pagsusuring HDCP"</item> - <item msgid="8254225038262324761">"Gamitin lang ang pagsusuring HDCP para sa nilalamang DRM"</item> + <item msgid="8254225038262324761">"Gamitin ang pagsusuring HDCP para sa content na DRM lang"</item> <item msgid="6421717003037072581">"Palaging gumamit ng pagsusuring HDCP"</item> </string-array> <string-array name="bt_hci_snoop_log_entries"> diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml index 73d3dd5205cd..7d4a4b49bc0d 100644 --- a/packages/SettingsLib/res/values-tl/strings.xml +++ b/packages/SettingsLib/res/values-tl/strings.xml @@ -266,7 +266,7 @@ <string name="bugreport_in_power" msgid="8664089072534638709">"Shortcut ng ulat sa bug"</string> <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Magpakita ng button sa power menu sa pagkuha ng ulat sa bug"</string> <string name="keep_screen_on" msgid="1187161672348797558">"Manatiling gumagana"</string> - <string name="keep_screen_on_summary" msgid="1510731514101925829">"Hindi kailanman hihinto ang screen kapag kinakargahan"</string> + <string name="keep_screen_on_summary" msgid="1510731514101925829">"Hindi kailanman hihinto ang screen kapag nagcha-charge"</string> <string name="bt_hci_snoop_log" msgid="7291287955649081448">"I-enable ang Bluetooth HCI snoop log"</string> <string name="bt_hci_snoop_log_summary" msgid="6808538971394092284">"I-capture ang mga Bluetooth packet. (I-toggle ang Bluetooth pagkatapos baguhin ang setting na ito)"</string> <string name="oem_unlock_enable" msgid="5334869171871566731">"Pag-a-unlock ng OEM"</string> @@ -367,7 +367,7 @@ <string name="show_screen_updates" msgid="2078782895825535494">"Ipakita update sa surface"</string> <string name="show_screen_updates_summary" msgid="2126932969682087406">"I-flash ang buong window surface kapag nag-update"</string> <string name="show_hw_screen_updates" msgid="2021286231267747506">"Ipakita update ng view"</string> - <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"I-flash mga view sa loob ng window kapag na-draw"</string> + <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"I-flash ang views sa loob ng window kapag na-draw"</string> <string name="show_hw_layers_updates" msgid="5268370750002509767">"Ipakita ang mga update ng hardware layers"</string> <string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"I-flash nang berde ang hardware layer pag nag-update ito"</string> <string name="debug_hw_overdraw" msgid="8944851091008756796">"I-debug ang GPU overdraw"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"I-scan ang QR code"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Para simulang makinig, igitna ang QR code sa ibaba"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"Hindi valid na format ang QR code"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Ihinto ang pag-broadcast ng <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Kung magbo-broadcast ka ng <xliff:g id="SWITCHAPP">%1$s</xliff:g> o babaguhin mo ang output, hihinto ang iyong kasalukuyang broadcast"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"I-broadcast ang <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Baguhin ang output"</string> </resources> diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml index cca694b2f887..5e5b42756043 100644 --- a/packages/SettingsLib/res/values-tr/strings.xml +++ b/packages/SettingsLib/res/values-tr/strings.xml @@ -280,7 +280,7 @@ <string name="wifi_display_certification" msgid="1805579519992520381">"Kablosuz ekran sertifikası"</string> <string name="wifi_verbose_logging" msgid="1785910450009679371">"Kablosuz Ayrıntılı Günlük Kaydını etkinleştir"</string> <string name="wifi_scan_throttling" msgid="2985624788509913617">"Kablosuz ağ taramasını kısma"</string> - <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"Kablosuz kalıcı olmayan MAC rastgele hale getirme süreci"</string> + <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"Kablosuz kalıcı olmayan MAC rastgele hale getirme modu"</string> <string name="mobile_data_always_on" msgid="8275958101875563572">"Mobil veri her zaman etkin"</string> <string name="tethering_hardware_offload" msgid="4116053719006939161">"Tethering donanım hızlandırıcısı"</string> <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Adsız Bluetooth cihazlarını göster"</string> @@ -380,7 +380,7 @@ <string name="debug_layout" msgid="1659216803043339741">"Düzen sınırlarını göster"</string> <string name="debug_layout_summary" msgid="8825829038287321978">"Klip sınırlarını, kenar boşluklarını vb. göster"</string> <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"Sağdan sola düzenini zorla"</string> - <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Tüm yerel ayarlar için sağdan sola ekran düzenini zorlar"</string> + <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Tüm yerel ayarlar için sağdan sola ekran düzenini zorla"</string> <string name="window_blurs" msgid="6831008984828425106">"Pencere bulanıklaştırmaya izin ver"</string> <string name="force_msaa" msgid="4081288296137775550">"4x MSAA\'yı zorla"</string> <string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 uygulamalarda 4x MSAA\'yı etkinleştir"</string> @@ -399,7 +399,7 @@ <string name="immediately_destroy_activities_summary" msgid="6289590341144557614">"Kullanıcının ayrıldığı her etkinliği hemen yok et"</string> <string name="app_process_limit_title" msgid="8361367869453043007">"Arka plan işlem sınırı"</string> <string name="show_all_anrs" msgid="9160563836616468726">"Arka plan ANR\'leri göster"</string> - <string name="show_all_anrs_summary" msgid="8562788834431971392">"Arka plan uygulamalar için Uygulama Yanıt Vermiyor mesajını göster"</string> + <string name="show_all_anrs_summary" msgid="8562788834431971392">"Arka plan uygulamalar için Uygulama Yanıt Vermiyor iletişimini göster"</string> <string name="show_notification_channel_warnings" msgid="3448282400127597331">"Bildirim kanalı uyarılarını göster"</string> <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"Bir uygulama geçerli kanal olmadan bildirim yayınladığında ekranda uyarı gösterir"</string> <string name="force_allow_on_external" msgid="9187902444231637880">"Harici birimdeki uygulamalara izin vermeye zorla"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR kodunu tara"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Dinlemeye başlamak için aşağıdaki QR kodunu ortalayın"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR kodu geçerli bir biçim değil"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulamasında anons durdurulsun mu?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> uygulamasında anons yapar veya çıkışı değiştirirseniz mevcut anonsunuz duraklatılır"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> uygulamasında anons yapın"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Çıkışı değiştirme"</string> </resources> diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml index 0f4ee0d05806..b068670f8036 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -151,7 +151,7 @@ <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Скасувати"</string> <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Якщо ви під’єднаєте інший пристрій, він матиме доступ до ваших контактів та історії дзвінків."</string> <string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"Не вдалося створити пару з пристроєм <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> - <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Не вдалося створити пару з пристроєм <xliff:g id="DEVICE_NAME">%1$s</xliff:g> через неправильний PIN-код чи ключ доступу."</string> + <string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"Помилка підключення до пристрою <xliff:g id="DEVICE_NAME">%1$s</xliff:g>: неправильний PIN-код чи ключ доступу."</string> <string name="bluetooth_pairing_device_down_error_message" msgid="2554424863101358857">"Неможливо зв’язатися з пристроєм <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> <string name="bluetooth_pairing_rejected_error_message" msgid="5943444352777314442">"Створ. пари відхилено <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string> <string name="bluetooth_talkback_computer" msgid="3736623135703893773">"Комп’ютер"</string> @@ -644,7 +644,7 @@ <string name="dream_complication_title_weather" msgid="598609151677172783">"Погода"</string> <string name="dream_complication_title_aqi" msgid="4587552608957834110">"Якість повітря"</string> <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Акторський склад"</string> - <string name="avatar_picker_title" msgid="8492884172713170652">"Вибрати зображення профілю"</string> + <string name="avatar_picker_title" msgid="8492884172713170652">"Виберіть зображення профілю"</string> <string name="default_user_icon_description" msgid="6554047177298972638">"Значок користувача за умовчанням"</string> <string name="physical_keyboard_title" msgid="4811935435315835220">"Фізична клавіатура"</string> <string name="keyboard_layout_dialog_title" msgid="3927180147005616290">"Вибрати розкладку клавіатури"</string> diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml index ebbd45e8a885..1386e05985b5 100644 --- a/packages/SettingsLib/res/values-ur/strings.xml +++ b/packages/SettingsLib/res/values-ur/strings.xml @@ -279,7 +279,7 @@ <string name="debug_networking_category" msgid="6829757985772659599">"نیٹ ورکنگ"</string> <string name="wifi_display_certification" msgid="1805579519992520381">"وائرلیس ڈسپلے سرٹیفیکیشن"</string> <string name="wifi_verbose_logging" msgid="1785910450009679371">"Wi‑Fi وربوس لاگنگ فعال کریں"</string> - <string name="wifi_scan_throttling" msgid="2985624788509913617">"Wi‑Fi اسکین کو زبردستی روکا جا رہا ہے"</string> + <string name="wifi_scan_throttling" msgid="2985624788509913617">"Wi‑Fi اسکین کو زبردستی روکنا"</string> <string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"Wi-Fi غیر مستقل MAC کی رینڈمائزیشن"</string> <string name="mobile_data_always_on" msgid="8275958101875563572">"موبائل ڈیٹا ہمیشہ فعال رکھیں"</string> <string name="tethering_hardware_offload" msgid="4116053719006939161">"ٹیدرنگ ہارڈویئر سرعت کاری"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR کوڈ اسکین کریں"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"سننا شروع کرنے کے لیے، نیچے کے QR کوڈ کو سینٹر میں رکھیں"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR کوڈ درست فارمیٹ نہیں ہے"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> براڈکاسٹنگ روکیں؟"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"اگر آپ <xliff:g id="SWITCHAPP">%1$s</xliff:g> براڈکاسٹ کرتے ہیں یا آؤٹ پٹ کو تبدیل کرتے ہیں تو آپ کا موجودہ براڈکاسٹ رک جائے گا"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> پر براڈکاسٹ کریں"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"آؤٹ پٹ تبدیل کریں"</string> </resources> diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml index 783777986d3c..52cc9cbd7c03 100644 --- a/packages/SettingsLib/res/values-uz/strings.xml +++ b/packages/SettingsLib/res/values-uz/strings.xml @@ -327,7 +327,7 @@ <string name="allow_mock_location_summary" msgid="179780881081354579">"Joylashuv emulyatsiyasiga ruxsat berish"</string> <string name="debug_view_attributes" msgid="3539609843984208216">"Alomatlar tekshiruvini yoqish"</string> <string name="mobile_data_always_on_summary" msgid="1112156365594371019">"Mobil internet har doim yoniq tursin, hatto Wi-Fi yoniq bo‘lsa ham (bir tarmoqdan ikkinchisiga tezroq o‘tish uchun)."</string> - <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Modem rejimida apparatli tezlashtirishdan foydalanish (agar mavjud bo‘lsa)"</string> + <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Modem rejimida apparatli tezlatishdan foydalanish (mavjud bo‘lsa)."</string> <string name="adb_warning_title" msgid="7708653449506485728">"USB orqali nosozliklarni tuzatishga ruxsat berilsinmi?"</string> <string name="adb_warning_message" msgid="8145270656419669221">"USB orqali nosozliklarni aniqlash faqat dasturlash maqsadlarida yoqiladi. Undan maʼlumotlarni qurilmangiz va kompyuter o‘rtasida ko‘chirish, ilovalarni xabarnomasiz o‘rnatish va jurnal maʼlumotlarini o‘qish uchun foydalaniladi."</string> <string name="adbwifi_warning_title" msgid="727104571653031865">"Wi-Fi orqali debagging uchun ruxsat berilsinmi?"</string> @@ -375,14 +375,14 @@ <string name="disable_overlays_summary" msgid="1954852414363338166">"Ekranda tasvirlarni biriktirish uchun doim GPU ishlatilsin"</string> <string name="simulate_color_space" msgid="1206503300335835151">"Rang maydonini simulyatsiyalash"</string> <string name="enable_opengl_traces_title" msgid="4638773318659125196">"OpenGL trassasini yoqish"</string> - <string name="usb_audio_disable_routing" msgid="3367656923544254975">"Audio uzatishni o‘ch. qo‘yish (USB)"</string> - <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"Tashqi USB qurilmaga avto-yo‘naltirishni o‘ch. qo‘yish"</string> + <string name="usb_audio_disable_routing" msgid="3367656923544254975">"Audio uzatishni faolsizlantirish (USB)"</string> + <string name="usb_audio_disable_routing_summary" msgid="8768242894849534699">"Tashqi USB qurilmaga avto-yo‘naltirishni faolsizlantirish"</string> <string name="debug_layout" msgid="1659216803043339741">"Elementlar hoshiyasi"</string> <string name="debug_layout_summary" msgid="8825829038287321978">"Klip, maydon va h.k. chegaralarini ko‘rsatish"</string> <string name="force_rtl_layout_all_locales" msgid="8690762598501599796">"O‘ngdan chapga qarab yozish"</string> <string name="force_rtl_layout_all_locales_summary" msgid="6663016859517239880">"Barcha tillarda o‘ngdan chapga qarab yozish"</string> <string name="window_blurs" msgid="6831008984828425106">"Oyna xiralashga ruxsat"</string> - <string name="force_msaa" msgid="4081288296137775550">"4x MSAAni yoqish"</string> + <string name="force_msaa" msgid="4081288296137775550">"4x MSAA sozlamasini yoqish"</string> <string name="force_msaa_summary" msgid="9070437493586769500">"OpenGL ES 2.0 ilovasidan 4x MSAAni yoqish"</string> <string name="show_non_rect_clip" msgid="7499758654867881817">"To‘g‘ri burchakli bo‘lmagan kesishma amallarini tuzatish"</string> <string name="track_frame_time" msgid="522674651937771106">"HWUI ishlash vaqtining hisobi"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"QR kodni skanerlash"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Tinglashni boshlash uchun quyidagi QR kodni markazga joylang"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR xato formatda"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasiga translatsiya toʻxtatilsinmi?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Agar <xliff:g id="SWITCHAPP">%1$s</xliff:g> ilovasiga translatsiya qilsangiz yoki ovoz chiqishini oʻzgartirsangiz, joriy translatsiya toʻxtab qoladi"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"<xliff:g id="SWITCHAPP">%1$s</xliff:g> ilovasiga translatsiya"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Ovoz chiqishini oʻzgartirish"</string> </resources> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index dac955e33e48..1965942b82e8 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Quét mã QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Để bắt đầu nghe, hãy hướng máy ảnh vào mã QR bên dưới và căn sao cho mã nằm chính giữa"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"Định dạng của mã QR là không hợp lệ"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Dừng phát <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Nếu bạn phát <xliff:g id="SWITCHAPP">%1$s</xliff:g> hoặc thay đổi đầu ra, phiên truyền phát hiện tại sẽ dừng"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Phát <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Thay đổi đầu ra"</string> </resources> diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml index b669708462bd..9bb725a119d9 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -369,7 +369,7 @@ <string name="show_hw_screen_updates" msgid="2021286231267747506">"显示视图更新"</string> <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">"Flash 硬件层在进行更新时会显示为绿色"</string> + <string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"Flash 硬件层在更新时会显示为绿色"</string> <string name="debug_hw_overdraw" msgid="8944851091008756796">"调试 GPU 过度绘制"</string> <string name="disable_overlays" msgid="4206590799671557143">"停用 HW 叠加层"</string> <string name="disable_overlays_summary" msgid="1954852414363338166">"始终使用 GPU 进行屏幕合成"</string> @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"扫描二维码"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"将扫描器对准下方二维码,即可开始收听"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"二维码的格式无效"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"要停止广播“<xliff:g id="APP_NAME">%1$s</xliff:g>”的内容吗?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"如果广播“<xliff:g id="SWITCHAPP">%1$s</xliff:g>”的内容或更改输出来源,当前的广播就会停止"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"广播“<xliff:g id="SWITCHAPP">%1$s</xliff:g>”的内容"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"更改输出来源"</string> </resources> diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index 1cd9d227fddc..726827cc1054 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"掃瞄 QR 碼"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"如要開始收聽,請將掃瞄器對準下方的 QR 碼"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR 碼格式無效"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"要停止播送「<xliff:g id="APP_NAME">%1$s</xliff:g>」的內容嗎?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"如果播送「<xliff:g id="SWITCHAPP">%1$s</xliff:g>」的內容或變更輸出來源,系統就會停止播送目前的內容"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"播送「<xliff:g id="SWITCHAPP">%1$s</xliff:g>」的內容"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"變更輸出來源"</string> </resources> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index 8a85ed1a410d..f77e88905743 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"掃描 QR 圖碼"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"如要開始收聽,請將掃描器對準下方的 QR 圖碼"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"QR 圖碼格式無效"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"要停止播送「<xliff:g id="APP_NAME">%1$s</xliff:g>」的內容嗎?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"如果播送「<xliff:g id="SWITCHAPP">%1$s</xliff:g>」的內容或變更輸出來源,系統就會停止播送目前的內容"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"播送「<xliff:g id="SWITCHAPP">%1$s</xliff:g>」的內容"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"變更輸出來源"</string> </resources> diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index 6ef85d235bc8..1cb1fa443e15 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -655,12 +655,8 @@ <string name="bt_le_audio_scan_qr_code" msgid="3521809854780392679">"Skena ikhodi ye-QR"</string> <string name="bt_le_audio_scan_qr_code_scanner" msgid="4679500020630341107">"Ukuze uqale ukulalela, beka ikhodi ye-QR ngezansi"</string> <string name="bt_le_audio_qr_code_is_not_valid_format" msgid="6092191081849434734">"Ikhodi ye-QR ayiyona ifomethi evumelekile"</string> - <!-- no translation found for bt_le_audio_broadcast_dialog_title (5392738488989777074) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_sub_title (268234802198852753) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_switch_app (5749813313369517812) --> - <skip /> - <!-- no translation found for bt_le_audio_broadcast_dialog_different_output (2638402023060391333) --> - <skip /> + <string name="bt_le_audio_broadcast_dialog_title" msgid="5392738488989777074">"Misa ukusakaza i-<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> + <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Uma usakaza i-<xliff:g id="SWITCHAPP">%1$s</xliff:g> noma ushintsha okuphumayo, ukusakaza kwakho kwamanje kuzoma"</string> + <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Sakaza i-<xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> + <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Shintsha okuphumayo"</string> </resources> diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml index 8315e8b069c8..cbc79d2d5d93 100644 --- a/packages/SettingsLib/res/values/dimens.xml +++ b/packages/SettingsLib/res/values/dimens.xml @@ -120,4 +120,18 @@ <dimen name="qrcode_preview_margin">40dp</dimen> <dimen name="qrcode_preview_radius">30dp</dimen> <dimen name="qrcode_icon_size">27dp</dimen> + + <!-- Broadcast dialog --> + <dimen name="broadcast_dialog_title_img_margin_top">18dp</dimen> + <dimen name="broadcast_dialog_title_text_size">24sp</dimen> + <dimen name="broadcast_dialog_title_text_margin">16dp</dimen> + <dimen name="broadcast_dialog_title_text_margin_top">18dp</dimen> + <dimen name="broadcast_dialog_subtitle_text_size">14sp</dimen> + <dimen name="broadcast_dialog_icon_size">24dp</dimen> + <dimen name="broadcast_dialog_icon_margin_top">25dp</dimen> + <dimen name="broadcast_dialog_btn_radius">100dp</dimen> + <dimen name="broadcast_dialog_btn_margin_bottom">4dp</dimen> + <dimen name="broadcast_dialog_btn_text_size">16sp</dimen> + <dimen name="broadcast_dialog_btn_minHeight">44dp</dimen> + <dimen name="broadcast_dialog_margin">16dp</dimen> </resources> diff --git a/packages/SettingsLib/res/values/styles.xml b/packages/SettingsLib/res/values/styles.xml index 28cd27bf0cad..32345150531d 100644 --- a/packages/SettingsLib/res/values/styles.xml +++ b/packages/SettingsLib/res/values/styles.xml @@ -39,4 +39,49 @@ <item name="android:textColor">?android:attr/textColorPrimary</item> <item name="android:textDirection">locale</item> </style> + + <style name="BroadcastDialogTitleStyle"> + <item name="android:textAppearance">@style/TextAppearanceBroadcastDialogTitle</item> + <item name="android:layout_marginStart">@dimen/broadcast_dialog_title_text_margin</item> + <item name="android:layout_marginEnd">@dimen/broadcast_dialog_title_text_margin</item> + <item name="android:layout_marginTop">@dimen/broadcast_dialog_title_text_margin_top</item> + <item name="android:layout_marginBottom">18dp</item> + </style> + + <style name="TextAppearanceBroadcastDialogTitle" parent="@android:TextAppearance.DeviceDefault.Headline"> + <item name="android:textSize">@dimen/broadcast_dialog_title_text_size</item> + <item name="android:textColor">?android:attr/textColorPrimary</item> + <item name="android:textDirection">locale</item> + <item name="android:ellipsize">end</item> + </style> + + <style name="BroadcastDialogBodyStyle"> + <item name="android:textAppearance">@style/TextAppearanceBroadcastDialogSubTitle</item> + <item name="android:layout_margin">@dimen/broadcast_dialog_title_text_margin</item> + </style> + + <style name="TextAppearanceBroadcastDialogSubTitle" parent="@android:TextAppearance.DeviceDefault.Headline"> + <item name="android:textSize">@dimen/broadcast_dialog_subtitle_text_size</item> + <item name="android:textColor">?android:attr/textColorSecondary</item> + <item name="android:textDirection">locale</item> + <item name="android:ellipsize">end</item> + </style> + + <style name="BroadcastDialogButtonStyle"> + <item name="android:textAppearance">@style/TextAppearanceBroadcastDialogButton</item> + <item name="android:layout_width">match_parent</item> + <item name="android:layout_height">wrap_content</item> + <item name="android:layout_gravity">center</item> + <item name="android:gravity">center</item> + <item name="android:stateListAnimator">@null</item> + <item name="android:elevation">0dp</item> + <item name="android:minHeight">@dimen/broadcast_dialog_btn_minHeight</item> + <item name="android:background">@drawable/broadcast_dialog_btn_bg</item> + </style> + + <style name="TextAppearanceBroadcastDialogButton" parent="@android:TextAppearance.DeviceDefault.Headline"> + <item name="android:textColor">?android:attr/textColorPrimary</item> + <item name="android:textSize">@dimen/broadcast_dialog_btn_text_size</item> + </style> + </resources> diff --git a/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java b/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java index 0f340239cd24..ff00fb3282b1 100644 --- a/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java @@ -26,7 +26,6 @@ import android.system.Os; import android.system.StructUtsname; import android.telephony.PhoneNumberUtils; import android.telephony.SubscriptionInfo; -import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.BidiFormatter; import android.text.TextDirectionHeuristics; @@ -34,9 +33,7 @@ import android.text.TextUtils; import android.text.format.DateFormat; import android.util.Log; -import androidx.annotation.RequiresApi; import androidx.annotation.VisibleForTesting; -import androidx.core.os.BuildCompat; import java.io.BufferedReader; import java.io.FileReader; @@ -182,8 +179,10 @@ public class DeviceInfoUtils { SubscriptionInfo subscriptionInfo) { String formattedNumber = null; if (subscriptionInfo != null) { - final String rawNumber = getRawPhoneNumber( - context, subscriptionInfo.getSubscriptionId()); + final TelephonyManager telephonyManager = context.getSystemService( + TelephonyManager.class); + final String rawNumber = telephonyManager.createForSubscriptionId( + subscriptionInfo.getSubscriptionId()).getLine1Number(); if (!TextUtils.isEmpty(rawNumber)) { formattedNumber = PhoneNumberUtils.formatNumber(rawNumber); } @@ -195,10 +194,12 @@ public class DeviceInfoUtils { List<SubscriptionInfo> subscriptionInfoList) { StringBuilder sb = new StringBuilder(); if (subscriptionInfoList != null) { + final TelephonyManager telephonyManager = context.getSystemService( + TelephonyManager.class); final int count = subscriptionInfoList.size(); for (SubscriptionInfo subscriptionInfo : subscriptionInfoList) { - final String rawNumber = getRawPhoneNumber( - context, subscriptionInfo.getSubscriptionId()); + final String rawNumber = telephonyManager.createForSubscriptionId( + subscriptionInfo.getSubscriptionId()).getLine1Number(); if (!TextUtils.isEmpty(rawNumber)) { sb.append(PhoneNumberUtils.formatNumber(rawNumber)).append("\n"); } @@ -218,21 +219,4 @@ public class DeviceInfoUtils { final String phoneNumber = getFormattedPhoneNumber(context, subscriptionInfo); return BidiFormatter.getInstance().unicodeWrap(phoneNumber, TextDirectionHeuristics.LTR); } - - private static String getRawPhoneNumber(Context context, int subscriptionId) { - if (BuildCompat.isAtLeastT()) { - return getRawPhoneNumberFromT(context, subscriptionId); - } else { - final TelephonyManager telephonyManager = context.getSystemService( - TelephonyManager.class); - return telephonyManager.createForSubscriptionId(subscriptionId).getLine1Number(); - } - } - - @RequiresApi(Build.VERSION_CODES.TIRAMISU) - private static String getRawPhoneNumberFromT(Context context, int subscriptionId) { - final SubscriptionManager subscriptionManager = context.getSystemService( - SubscriptionManager.class); - return subscriptionManager.getPhoneNumber(subscriptionId); - } } diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java index 3a4a8d27b2f3..284da73efb6f 100644 --- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java +++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java @@ -31,10 +31,11 @@ import android.util.TypedValue; import android.widget.TextView; import androidx.annotation.RequiresApi; -import androidx.core.os.BuildCompat; import androidx.preference.Preference; import androidx.preference.PreferenceViewHolder; +import com.android.settingslib.utils.BuildCompatUtils; + /** * Helper class for managing settings preferences that can be disabled * by device admins via user restrictions. @@ -105,7 +106,7 @@ public class RestrictedPreferenceHelper { if (mDisabledSummary) { final TextView summaryView = (TextView) holder.findViewById(android.R.id.summary); if (summaryView != null) { - final CharSequence disabledText = BuildCompat.isAtLeastT() + final CharSequence disabledText = BuildCompatUtils.isAtLeastT() ? getDisabledByAdminUpdatableString() : mContext.getString(R.string.disabled_by_admin_summary_text); if (mDisabledByAdmin) { diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java index aaa011458258..feb4212035bc 100644 --- a/packages/SettingsLib/src/com/android/settingslib/Utils.java +++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java @@ -45,7 +45,6 @@ import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; import androidx.core.graphics.drawable.RoundedBitmapDrawable; import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; -import androidx.core.os.BuildCompat; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.UserIcons; @@ -53,6 +52,7 @@ import com.android.launcher3.icons.BaseIconFactory.IconOptions; import com.android.launcher3.icons.IconFactory; import com.android.settingslib.drawable.UserIconDrawable; import com.android.settingslib.fuelgauge.BatteryStatus; +import com.android.settingslib.utils.BuildCompatUtils; import java.text.NumberFormat; @@ -130,7 +130,7 @@ public class Utils { String name = info != null ? info.name : null; if (info.isManagedProfile()) { // We use predefined values for managed profiles - return BuildCompat.isAtLeastT() + return BuildCompatUtils.isAtLeastT() ? getUpdatableManagedUserTitle(context) : context.getString(R.string.managed_user_title); } else if (info.isGuest()) { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BroadcastDialog.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BroadcastDialog.java new file mode 100644 index 000000000000..cb4eba422366 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BroadcastDialog.java @@ -0,0 +1,66 @@ +/** + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.bluetooth; + +import android.app.AlertDialog; +import android.content.Context; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.TextView; + +import com.android.settingslib.R; + +public class BroadcastDialog extends AlertDialog { + + private static final String TAG = "BroadcastDialog"; + + private String mCurrentApp; + private String mSwitchApp; + private Context mContext; + + public BroadcastDialog(Context context) { + super(context); + mContext = context; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + + View layout = View.inflate(mContext, R.layout.broadcast_dialog, null); + final Window window = getWindow(); + window.setContentView(layout); + window.setWindowAnimations(R.style.Theme_AlertDialog_SettingsLib); + + TextView title = layout.findViewById(R.id.dialog_title); + TextView subTitle = layout.findViewById(R.id.dialog_subtitle); + title.setText(mContext.getString(R.string.bt_le_audio_broadcast_dialog_title, mCurrentApp)); + subTitle.setText( + mContext.getString(R.string.bt_le_audio_broadcast_dialog_sub_title, mSwitchApp)); + Button positiveBtn = layout.findViewById(R.id.positive_btn); + Button negativeBtn = layout.findViewById(R.id.negative_btn); + Button neutralBtn = layout.findViewById(R.id.neutral_btn); + positiveBtn.setText(mContext.getString( + R.string.bt_le_audio_broadcast_dialog_switch_app, mSwitchApp), null); + neutralBtn.setOnClickListener((view) -> { + Log.d(TAG, "BroadcastDialog dismiss."); + dismiss(); + }); + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java index 94d90a8eb028..11fae24aa677 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java @@ -47,7 +47,8 @@ import android.os.UserHandle; import androidx.annotation.RequiresApi; import androidx.annotation.VisibleForTesting; -import androidx.core.os.BuildCompat; + +import com.android.settingslib.utils.BuildCompatUtils; /** * Converts the user avatar icon to a circularly clipped one with an optional badge and frame @@ -87,7 +88,7 @@ public class UserIconDrawable extends Drawable implements Drawable.Callback { * @return drawable containing just the badge */ public static Drawable getManagedUserDrawable(Context context) { - if (BuildCompat.isAtLeastT()) { + if (BuildCompatUtils.isAtLeastT()) { return getUpdatableManagedUserDrawable(context); } else { return getDrawableForDisplayDensity( @@ -176,6 +177,10 @@ public class UserIconDrawable extends Drawable implements Drawable.Callback { return this; } + public boolean isEmpty() { + return getUserIcon() == null && getUserDrawable() == null; + } + public UserIconDrawable setBadge(Drawable badge) { mBadge = badge; if (mBadge != null) { @@ -222,7 +227,7 @@ public class UserIconDrawable extends Drawable implements Drawable.Callback { } private static Drawable getManagementBadge(Context context) { - if (BuildCompat.isAtLeastT()) { + if (BuildCompatUtils.isAtLeastT()) { return getUpdatableManagementBadge(context); } else { return getDrawableForDisplayDensity( diff --git a/packages/SettingsLib/src/com/android/settingslib/qrcode/QrCodeScanModeActivity.java b/packages/SettingsLib/src/com/android/settingslib/qrcode/QrCodeScanModeActivity.java index 9021fcbc3f99..15a910e13aa8 100644 --- a/packages/SettingsLib/src/com/android/settingslib/qrcode/QrCodeScanModeActivity.java +++ b/packages/SettingsLib/src/com/android/settingslib/qrcode/QrCodeScanModeActivity.java @@ -26,8 +26,8 @@ import android.util.Log; import androidx.fragment.app.FragmentTransaction; -import com.android.settingslib.bluetooth.BluetoothBroadcastUtils; import com.android.settingslib.R; +import com.android.settingslib.bluetooth.BluetoothBroadcastUtils; import com.android.settingslib.bluetooth.BluetoothUtils; public class QrCodeScanModeActivity extends QrCodeScanModeBaseActivity { diff --git a/packages/SettingsLib/src/com/android/settingslib/qrcode/QrCodeScanModeBaseActivity.java b/packages/SettingsLib/src/com/android/settingslib/qrcode/QrCodeScanModeBaseActivity.java index 9aaec41e721a..361fd5b57556 100644 --- a/packages/SettingsLib/src/com/android/settingslib/qrcode/QrCodeScanModeBaseActivity.java +++ b/packages/SettingsLib/src/com/android/settingslib/qrcode/QrCodeScanModeBaseActivity.java @@ -1,4 +1,4 @@ -/* +/** * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,8 +21,8 @@ import android.os.Bundle; import androidx.fragment.app.FragmentManager; -import com.android.settingslib.core.lifecycle.ObservableActivity; import com.android.settingslib.R; +import com.android.settingslib.core.lifecycle.ObservableActivity; public abstract class QrCodeScanModeBaseActivity extends ObservableActivity { diff --git a/packages/SettingsLib/src/com/android/settingslib/qrcode/QrCodeScanModeController.java b/packages/SettingsLib/src/com/android/settingslib/qrcode/QrCodeScanModeController.java index d7640bb1b564..153d2d20e801 100644 --- a/packages/SettingsLib/src/com/android/settingslib/qrcode/QrCodeScanModeController.java +++ b/packages/SettingsLib/src/com/android/settingslib/qrcode/QrCodeScanModeController.java @@ -1,4 +1,4 @@ -/* +/** * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/packages/SettingsLib/src/com/android/settingslib/qrcode/QrCodeScanModeFragment.java b/packages/SettingsLib/src/com/android/settingslib/qrcode/QrCodeScanModeFragment.java index 81165aa3330c..069b9507ccef 100644 --- a/packages/SettingsLib/src/com/android/settingslib/qrcode/QrCodeScanModeFragment.java +++ b/packages/SettingsLib/src/com/android/settingslib/qrcode/QrCodeScanModeFragment.java @@ -1,4 +1,4 @@ -/* +/** * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,9 +35,9 @@ import android.view.ViewOutlineProvider; import android.view.accessibility.AccessibilityEvent; import android.widget.TextView; +import com.android.settingslib.R; import com.android.settingslib.bluetooth.BluetoothBroadcastUtils; import com.android.settingslib.bluetooth.BluetoothUtils; -import com.android.settingslib.R; import com.android.settingslib.core.lifecycle.ObservableFragment; import androidx.annotation.NonNull; diff --git a/packages/SettingsLib/src/com/android/settingslib/qrcode/QrDecorateView.java b/packages/SettingsLib/src/com/android/settingslib/qrcode/QrDecorateView.java index 7005d3638f9e..51cf59c25502 100644 --- a/packages/SettingsLib/src/com/android/settingslib/qrcode/QrDecorateView.java +++ b/packages/SettingsLib/src/com/android/settingslib/qrcode/QrDecorateView.java @@ -1,4 +1,4 @@ -/* +/** * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/packages/SettingsLib/src/com/android/settingslib/qrcode/QrYuvLuminanceSource.java b/packages/SettingsLib/src/com/android/settingslib/qrcode/QrYuvLuminanceSource.java index 421cf5c40b69..33f0cddb22e0 100644 --- a/packages/SettingsLib/src/com/android/settingslib/qrcode/QrYuvLuminanceSource.java +++ b/packages/SettingsLib/src/com/android/settingslib/qrcode/QrYuvLuminanceSource.java @@ -1,4 +1,4 @@ -/* +/** * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtils.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtils.java index 6535665b7653..d97c819e88ef 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtils.java @@ -18,7 +18,6 @@ package com.android.settingslib.wifi; import android.content.Context; import android.os.Build; -import android.os.Bundle; import android.os.UserManager; import android.util.Log; @@ -37,13 +36,9 @@ public class WifiEnterpriseRestrictionUtils { * @return whether the device is permitted to use Wi-Fi Tethering */ public static boolean isWifiTetheringAllowed(Context context) { - final UserManager userManager = context.getSystemService(UserManager.class); - final Bundle restrictions = userManager.getUserRestrictions(); - if (isAtLeastT() && restrictions.getBoolean(UserManager.DISALLOW_WIFI_TETHERING)) { - Log.i(TAG, "Wi-Fi Tethering isn't available due to user restriction."); - return false; - } - return true; + if (!hasUserRestrictionFromT(context, UserManager.DISALLOW_WIFI_TETHERING)) return true; + Log.w(TAG, "Wi-Fi Tethering isn't available due to user restriction."); + return false; } /** @@ -53,13 +48,9 @@ public class WifiEnterpriseRestrictionUtils { * @return whether the device is permitted to use Wi-Fi Direct */ public static boolean isWifiDirectAllowed(Context context) { - final UserManager userManager = context.getSystemService(UserManager.class); - final Bundle restrictions = userManager.getUserRestrictions(); - if (isAtLeastT() && restrictions.getBoolean(UserManager.DISALLOW_WIFI_DIRECT)) { - Log.i(TAG, "Wi-Fi Direct isn't available due to user restriction."); - return false; - } - return true; + if (!hasUserRestrictionFromT(context, UserManager.DISALLOW_WIFI_DIRECT)) return true; + Log.w(TAG, "Wi-Fi Direct isn't available due to user restriction."); + return false; } /** @@ -69,13 +60,9 @@ public class WifiEnterpriseRestrictionUtils { * @return whether the device is permitted to add new Wi-Fi config */ public static boolean isAddWifiConfigAllowed(Context context) { - final UserManager userManager = context.getSystemService(UserManager.class); - final Bundle restrictions = userManager.getUserRestrictions(); - if (isAtLeastT() && restrictions.getBoolean(UserManager.DISALLOW_ADD_WIFI_CONFIG)) { - Log.i(TAG, "Wi-Fi Add network isn't available due to user restriction."); - return false; - } - return true; + if (!hasUserRestrictionFromT(context, UserManager.DISALLOW_ADD_WIFI_CONFIG)) return true; + Log.w(TAG, "Wi-Fi Add network isn't available due to user restriction."); + return false; } /** @@ -98,7 +85,7 @@ public class WifiEnterpriseRestrictionUtils { return userManager.hasUserRestriction(restrictionKey); } - @ChecksSdkIntAtLeast(api=Build.VERSION_CODES.TIRAMISU) + @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.TIRAMISU) private static boolean isAtLeastT() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU; } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtilsTest.java index e9326dd39faa..af9e69a8270c 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtilsTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtilsTest.java @@ -15,122 +15,91 @@ */ package com.android.settingslib.wifi; +import static android.os.UserManager.DISALLOW_ADD_WIFI_CONFIG; import static android.os.UserManager.DISALLOW_CHANGE_WIFI_STATE; +import static android.os.UserManager.DISALLOW_WIFI_DIRECT; +import static android.os.UserManager.DISALLOW_WIFI_TETHERING; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.content.Context; import android.os.Build; -import android.os.Bundle; import android.os.UserManager; import androidx.test.core.app.ApplicationProvider; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; import org.robolectric.util.ReflectionHelpers; @RunWith(RobolectricTestRunner.class) public class WifiEnterpriseRestrictionUtilsTest { - private Context mContext; + static final String SDK_INT = "SDK_INT"; + static final int VERSION_CODES_S = Build.VERSION_CODES.S; + static final int VERSION_CODES_T = Build.VERSION_CODES.TIRAMISU; + + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Spy + Context mContext = ApplicationProvider.getApplicationContext(); @Mock private UserManager mUserManager; - @Mock - private Bundle mBundle; @Before public void setUp() { - MockitoAnnotations.initMocks(this); - mContext = spy(ApplicationProvider.getApplicationContext()); when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager); - when(mUserManager.getUserRestrictions()).thenReturn(mBundle); - ReflectionHelpers.setStaticField( - Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.TIRAMISU); + ReflectionHelpers.setStaticField(Build.VERSION.class, SDK_INT, VERSION_CODES_T); } @Test - public void isWifiTetheringAllowed_setSDKForS_shouldReturnTrue() { - ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.S); - when(mBundle.getBoolean(UserManager.DISALLOW_WIFI_TETHERING)).thenReturn(true); - - assertThat(WifiEnterpriseRestrictionUtils.isWifiTetheringAllowed(mContext)).isTrue(); - } - - @Test - public void isWifiTetheringAllowed_setSDKForTAndDisallowForRestriction_shouldReturnFalse() { - ReflectionHelpers.setStaticField( - Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.TIRAMISU); - when(mBundle.getBoolean(UserManager.DISALLOW_WIFI_TETHERING)).thenReturn(true); + public void isWifiTetheringAllowed_hasDisallowRestriction_shouldReturnFalse() { + when(mUserManager.hasUserRestriction(DISALLOW_WIFI_TETHERING)).thenReturn(true); assertThat(WifiEnterpriseRestrictionUtils.isWifiTetheringAllowed(mContext)).isFalse(); } @Test - public void isWifiTetheringAllowed_setSDKForTAndAllowForRestriction_shouldReturnTrue() { - ReflectionHelpers.setStaticField( - Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.TIRAMISU); - when(mBundle.getBoolean(UserManager.DISALLOW_WIFI_TETHERING)).thenReturn(false); + public void isWifiTetheringAllowed_noDisallowRestriction_shouldReturnTrue() { + when(mUserManager.hasUserRestriction(DISALLOW_WIFI_TETHERING)).thenReturn(false); assertThat(WifiEnterpriseRestrictionUtils.isWifiTetheringAllowed(mContext)).isTrue(); } @Test - public void isWifiDirectAllowed_setSDKForS_shouldReturnTrue() { - ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.S); - when(mBundle.getBoolean(UserManager.DISALLOW_WIFI_DIRECT)).thenReturn(true); - - assertThat(WifiEnterpriseRestrictionUtils.isWifiDirectAllowed(mContext)).isTrue(); - } - - @Test - public void isWifiDirectAllowed_setSDKForTAndDisallowForRestriction_shouldReturnFalse() { - ReflectionHelpers.setStaticField( - Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.TIRAMISU); - when(mBundle.getBoolean(UserManager.DISALLOW_WIFI_DIRECT)).thenReturn(true); + public void isWifiDirectAllowed_hasDisallowRestriction_shouldReturnFalse() { + when(mUserManager.hasUserRestriction(DISALLOW_WIFI_DIRECT)).thenReturn(true); assertThat(WifiEnterpriseRestrictionUtils.isWifiDirectAllowed(mContext)).isFalse(); } @Test - public void isWifiDirectAllowed_setSDKForTAndAllowForRestriction_shouldReturnTrue() { - ReflectionHelpers.setStaticField( - Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.TIRAMISU); - when(mBundle.getBoolean(UserManager.DISALLOW_WIFI_DIRECT)).thenReturn(false); + public void isWifiDirectAllowed_noDisallowRestriction_shouldReturnTrue() { + when(mUserManager.hasUserRestriction(DISALLOW_WIFI_DIRECT)).thenReturn(false); assertThat(WifiEnterpriseRestrictionUtils.isWifiDirectAllowed(mContext)).isTrue(); } @Test - public void isAddWifiConfigAllowed_setSDKForS_shouldReturnTrue() { - ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.S); - when(mBundle.getBoolean(UserManager.DISALLOW_ADD_WIFI_CONFIG)).thenReturn(true); - - assertThat(WifiEnterpriseRestrictionUtils.isAddWifiConfigAllowed(mContext)).isTrue(); - } - - @Test - public void isAddWifiConfigAllowed_setSDKForTAndDisallowForRestriction_shouldReturnFalse() { - ReflectionHelpers.setStaticField( - Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.TIRAMISU); - when(mBundle.getBoolean(UserManager.DISALLOW_ADD_WIFI_CONFIG)).thenReturn(true); + public void isAddWifiConfigAllowed_hasDisallowRestriction_shouldReturnFalse() { + when(mUserManager.hasUserRestriction(DISALLOW_ADD_WIFI_CONFIG)).thenReturn(true); assertThat(WifiEnterpriseRestrictionUtils.isAddWifiConfigAllowed(mContext)).isFalse(); } @Test - public void isAddWifiConfigAllowed_setSDKForTAndAllowForRestriction_shouldReturnTrue() { - ReflectionHelpers.setStaticField( - Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.TIRAMISU); - when(mBundle.getBoolean(UserManager.DISALLOW_ADD_WIFI_CONFIG)).thenReturn(false); + public void isAddWifiConfigAllowed_noDisallowRestriction_shouldReturnTrue() { + when(mUserManager.hasUserRestriction(DISALLOW_ADD_WIFI_CONFIG)).thenReturn(false); assertThat(WifiEnterpriseRestrictionUtils.isAddWifiConfigAllowed(mContext)).isTrue(); } @@ -143,7 +112,7 @@ public class WifiEnterpriseRestrictionUtilsTest { } @Test - public void isChangeWifiStateAllowed_hasNoDisallowRestriction_shouldReturnTrue() { + public void isChangeWifiStateAllowed_noDisallowRestriction_shouldReturnTrue() { when(mUserManager.hasUserRestriction(DISALLOW_CHANGE_WIFI_STATE)).thenReturn(false); assertThat(WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(mContext)).isTrue(); @@ -151,7 +120,7 @@ public class WifiEnterpriseRestrictionUtilsTest { @Test public void hasUserRestrictionFromT_setSDKForS_shouldReturnTrue() { - ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.S); + ReflectionHelpers.setStaticField(Build.VERSION.class, SDK_INT, VERSION_CODES_S); assertThat(WifiEnterpriseRestrictionUtils.hasUserRestrictionFromT(mContext, "key")) .isFalse(); @@ -159,8 +128,7 @@ public class WifiEnterpriseRestrictionUtilsTest { @Test public void hasUserRestrictionFromT_setSDKForT_shouldReturnHasUserRestriction() { - ReflectionHelpers.setStaticField( - Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.TIRAMISU); + ReflectionHelpers.setStaticField(Build.VERSION.class, SDK_INT, VERSION_CODES_T); when(mUserManager.hasUserRestriction(anyString())).thenReturn(false); assertThat(WifiEnterpriseRestrictionUtils.hasUserRestrictionFromT(mContext, "key")) diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java index 716ee845bea6..a6bfc408be7e 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java @@ -43,7 +43,6 @@ public class SystemSettings { Settings.System.FONT_SCALE, Settings.System.DIM_SCREEN, Settings.System.SCREEN_OFF_TIMEOUT, - Settings.System.SCREEN_OFF_TIMEOUT_DOCKED, Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, Settings.System.SCREEN_BRIGHTNESS_FOR_VR, diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java index d4302963f2d3..06712cc68b89 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java @@ -111,7 +111,6 @@ public class SystemSettingsValidators { }); VALIDATORS.put(System.DISPLAY_COLOR_MODE_VENDOR_HINT, ANY_STRING_VALIDATOR); VALIDATORS.put(System.SCREEN_OFF_TIMEOUT, NON_NEGATIVE_INTEGER_VALIDATOR); - VALIDATORS.put(System.SCREEN_OFF_TIMEOUT_DOCKED, NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put(System.SCREEN_BRIGHTNESS_FOR_VR, new InclusiveIntegerRangeValidator(0, 255)); VALIDATORS.put(System.SCREEN_BRIGHTNESS_MODE, BOOLEAN_VALIDATOR); VALIDATORS.put(System.ADAPTIVE_SLEEP, BOOLEAN_VALIDATOR); diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index a28c4cf6b0d4..3b862ffbbd9e 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -686,6 +686,9 @@ <!-- Permission required for CTS test - CtsKeystoreTestCases --> <uses-permission android:name="android.permission.REQUEST_UNIQUE_ID_ATTESTATION" /> + <!-- Permission required for CTS test - CtsDevicePolicyManagerTestCases --> + <uses-permission android:name="android.permission.READ_NEARBY_STREAMING_POLICY" /> + <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" android:defaultToDeviceProtectedStorage="true" diff --git a/packages/Shell/res/values-as/strings.xml b/packages/Shell/res/values-as/strings.xml index 6e80931e3619..9b9db6e872be 100644 --- a/packages/Shell/res/values-as/strings.xml +++ b/packages/Shell/res/values-as/strings.xml @@ -28,7 +28,7 @@ <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"ষ্ক্ৰীণশ্বট নোলোৱাকৈ বাগ সম্পৰ্কীয় অভিযোগ শ্বেয়াৰ কৰিবলৈ বাছনি কৰক বা ষ্ক্ৰীণশ্বট লোৱা কাৰ্য সম্পূৰ্ণ হোৱালৈ অপেক্ষা কৰক"</string> <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"স্ক্ৰীণশ্বট নোলোৱাকৈ বাগ সম্পর্কীয় অভিযোগ শ্বেয়াৰ কৰিবলৈ ইয়াত টিপক বা স্ক্ৰীণশ্বট সম্পূৰ্ণ হোৱালৈ অপেক্ষা কৰক"</string> <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"স্ক্ৰীণশ্বট নোলোৱাকৈ বাগ সম্পর্কীয় অভিযোগ শ্বেয়াৰ কৰিবলৈ ইয়াত টিপক বা স্ক্ৰীণশ্বট সম্পূৰ্ণ হোৱালৈ অপেক্ষা কৰক"</string> - <string name="bugreport_confirm" msgid="5917407234515812495">"বাগ সম্পর্কীয় অভিযোগত ছিষ্টেমৰ বিভিন্ন লগ ফাইল থাকে, ইয়াৰ ভিতৰত আপুনি স্পর্শকাতৰ বুলি গণ্য কৰা ডেটা (যেনে এপৰ ব্য়ৱহাৰ আৰু অৱস্থান সম্পৰ্কীয় তথ্য়) অন্তর্ভুক্ত হ\'ব পাৰে। কেৱল আপোনাৰ বিশ্বাসী লোক বা এপৰ সৈতেহে বাগ সম্পর্কীয় অভিযোগ শ্বেয়াৰ কৰিব।"</string> + <string name="bugreport_confirm" msgid="5917407234515812495">"বাগ সম্পর্কীয় অভিযোগত ছিষ্টেমৰ বিভিন্ন লগ ফাইল থাকে, ইয়াৰ ভিতৰত আপুনি স্পর্শকাতৰ বুলি গণ্য কৰা ডেটা (যেনে এপৰ ব্যৱহাৰ আৰু অৱস্থান সম্পৰ্কীয় তথ্য) অন্তর্ভুক্ত হ\'ব পাৰে। কেৱল আপোনাৰ বিশ্বাসী লোক বা এপৰ সৈতেহে বাগ সম্পর্কীয় অভিযোগ শ্বেয়াৰ কৰিব।"</string> <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"পুনৰাই নেদেখুৱাব"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"বাগ সম্পর্কীয় প্ৰতিবেদনসমূহ"</string> <string name="bugreport_unreadable_text" msgid="586517851044535486">"বাগ সম্পর্কীয় অভিযোগৰ ফাইলটো পঢ়িব পৰা নগ\'ল"</string> diff --git a/packages/Shell/res/values-ky/strings.xml b/packages/Shell/res/values-ky/strings.xml index d73ee2fdb4e9..2f1ea033051f 100644 --- a/packages/Shell/res/values-ky/strings.xml +++ b/packages/Shell/res/values-ky/strings.xml @@ -28,7 +28,7 @@ <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Мүчүлүштүк тууралуу кабарды скриншотсуз жөнөтүү үчүн солго сүрүңүз же скриншот даяр болгуча күтүңүз"</string> <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Мүчүлүштүк тууралуу билдирүүңүздү скриншотсуз бөлүшүү үчүн таптап коюңуз же скриншот даяр болгуча күтө туруңуз"</string> <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Мүчүлүштүк тууралуу билдирүүңүздү скриншотсуз бөлүшүү үчүн таптап коюңуз же скриншот даяр болгуча күтө туруңуз"</string> - <string name="bugreport_confirm" msgid="5917407234515812495">"Мүчүлүштүктөр тууралуу билдирүүлөрдө тутумдун ар кандай таржымалдарынан алынган дайындар, ошондой эле купуя маалымат камтылышы мүмкүн (мисалы, жайгашкан жер сыяктуу). Мындай билдирүүлөрдү бир гана ишеничтүү адамдар жана колдонмолор менен бөлүшүңүз."</string> + <string name="bugreport_confirm" msgid="5917407234515812495">"Мүчүлүштүктөр тууралуу билдирүүлөрдө системанын ар кандай таржымалдарынан алынган дайындар, ошондой эле купуя маалымат камтылышы мүмкүн (мисалы, жайгашкан жер сыяктуу). Мындай билдирүүлөрдү бир гана ишеничтүү адамдар жана колдонмолор менен бөлүшүңүз."</string> <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Экинчи көрүнбөсүн"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Мүчүлүштүктөрдү кабарлоо"</string> <string name="bugreport_unreadable_text" msgid="586517851044535486">"Мүчүлүштүк тууралуу кабарлаган файл окулбай койду"</string> diff --git a/packages/SoundPicker/res/values-te/strings.xml b/packages/SoundPicker/res/values-te/strings.xml index 8f5c34a8018c..feaf4c83b51e 100644 --- a/packages/SoundPicker/res/values-te/strings.xml +++ b/packages/SoundPicker/res/values-te/strings.xml @@ -22,7 +22,7 @@ <string name="add_ringtone_text" msgid="6642389991738337529">"రింగ్టోన్ను జోడించు"</string> <string name="add_alarm_text" msgid="3545497316166999225">"అలారాన్ని జోడించు"</string> <string name="add_notification_text" msgid="4431129543300614788">"నోటిఫికేషన్ని జోడించు"</string> - <string name="delete_ringtone_text" msgid="201443984070732499">"తొలగించు"</string> + <string name="delete_ringtone_text" msgid="201443984070732499">"తొలగించండి"</string> <string name="unable_to_add_ringtone" msgid="4583511263449467326">"అనుకూల రింగ్టోన్ను జోడించలేకపోయింది"</string> <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"అనుకూల రింగ్టోన్ను తొలగించలేకపోయింది"</string> <string name="app_label" msgid="3091611356093417332">"ధ్వనులు"</string> diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index eb7fea3eb89a..6887d037c6f4 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -224,6 +224,7 @@ <uses-permission android:name="android.permission.MANAGE_NOTIFICATIONS" /> <uses-permission android:name="android.permission.GET_RUNTIME_PERMISSIONS" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> + <uses-permission android:name="android.permission.MANAGE_ROLE_HOLDERS" /> <!-- It's like, reality, but, you know, virtual --> <uses-permission android:name="android.permission.ACCESS_VR_MANAGER" /> @@ -522,7 +523,8 @@ android:launchMode="singleTop" android:permission="android.permission.MANAGE_SENSOR_PRIVACY" android:theme="@style/Theme.SystemUI.Dialog.Alert" - android:finishOnCloseSystemDialogs="true"> + android:finishOnCloseSystemDialogs="true" + android:showForAllUsers="true"> </activity> <!-- started from SensoryPrivacyService --> @@ -531,7 +533,8 @@ android:launchMode="singleTop" android:permission="android.permission.MANAGE_SENSOR_PRIVACY" android:theme="@style/BottomSheet" - android:finishOnCloseSystemDialogs="true"> + android:finishOnCloseSystemDialogs="true" + android:showForAllUsers="true"> </activity> diff --git a/packages/SystemUI/docs/usb_audio.md b/packages/SystemUI/docs/usb_audio.md new file mode 100644 index 000000000000..66e2df944fbc --- /dev/null +++ b/packages/SystemUI/docs/usb_audio.md @@ -0,0 +1,30 @@ +# USB audio Permission and Confirmation warning dialog resource string id matrix table +### go/support-usb-access-aoc-offload-feature + + |---|------------|----------------|------------------|-----------------|--------------------| + | # | Permission |isUsbAudioDevice| hasAudioPlayback | hasAudioCapture | string resource ID | + |---|------------|----------------|------------------|-----------------|--------------------| + | 1 | TRUE | TRUE | TRUE | FALSE | usb_audio_device_ + permission_prompt | + |---|------------|----------------|------------------|-----------------|--------------------| + | 2 | TRUE | TRUE | FALSE | TRUE | usb_audio_device_ + permission_prompt | + |---|------------|----------------|------------------|-----------------|--------------------| + | 3 | TRUE | TRUE | TRUE | TRUE | usb_audio_device_ + permission_prompt | + |---|------------|----------------|------------------|-----------------|--------------------| + | 4 | TRUE | FALSE | N/A | N/A | usb_device_ + permission_prompt | + |---|------------|----------------|------------------|-----------------|--------------------| + | 5 | FALSE | TRUE | TRUE | FALSE | usb_audio_device_ + permission_prompt | + |---|------------|----------------|------------------|-----------------|--------------------| + | 6 | FALSE | TRUE | FALSE | TRUE | usb_audio_device_ + permission_prompt_warn + |---|------------|----------------|------------------|-----------------|--------------------| + | 7 | FALSE | TRUE | TRUE | TRUE | usb_audio_device_ + permission_prompt_warn + |---|------------|----------------|------------------|-----------------|--------------------| + | 8 | FALSE | FALSE | N/A | N/A | usb_device_ + permission_prompt | + |---|------------|----------------|------------------|-----------------|--------------------| diff --git a/packages/SystemUI/res-keyguard/values-sw600dp-land/dimens.xml b/packages/SystemUI/res-keyguard/values-sw600dp-land/dimens.xml index ca8554cbbbfb..96949995670f 100644 --- a/packages/SystemUI/res-keyguard/values-sw600dp-land/dimens.xml +++ b/packages/SystemUI/res-keyguard/values-sw600dp-land/dimens.xml @@ -22,6 +22,6 @@ <!-- Overload default clock widget parameters --> <dimen name="widget_big_font_size">88dp</dimen> - <dimen name="qs_panel_padding_top">@dimen/qqs_layout_margin_top</dimen> + <dimen name="qs_panel_padding_top">16dp</dimen> </resources>
\ No newline at end of file diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml index dd42d7764db4..54ff7ad85908 100644 --- a/packages/SystemUI/res-keyguard/values-te/strings.xml +++ b/packages/SystemUI/res-keyguard/values-te/strings.xml @@ -45,7 +45,7 @@ <string name="keyguard_accessibility_password" msgid="3524161948484801450">"పరికరం పాస్వర్డ్"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM పిన్ ప్రాంతం"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM PUK ప్రాంతం"</string> - <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"తొలగించు"</string> + <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"తొలగించండి"</string> <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIMని నిలిపివేయండి"</string> <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIMని నిలపడం సాధ్యపడదు"</string> <string name="error_disable_esim_msg" msgid="2441188596467999327">"ఎర్రర్ కారణంగా eSIMని నిలపడం సాధ్యపడదు."</string> diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml index 9a6f5edae5ec..77f1803523a8 100644 --- a/packages/SystemUI/res-keyguard/values/dimens.xml +++ b/packages/SystemUI/res-keyguard/values/dimens.xml @@ -38,6 +38,9 @@ <!-- Margin around the various security views --> <dimen name="keyguard_security_view_top_margin">8dp</dimen> + <!-- Minimum bottom margin under the security view --> + <dimen name="keyguard_security_view_bottom_margin">60dp</dimen> + <dimen name="keyguard_eca_top_margin">18dp</dimen> <dimen name="keyguard_eca_bottom_margin">12dp</dimen> diff --git a/packages/SystemUI/res/anim/media_metadata_enter.xml b/packages/SystemUI/res/anim/media_metadata_enter.xml new file mode 100644 index 000000000000..fccb7667c41c --- /dev/null +++ b/packages/SystemUI/res/anim/media_metadata_enter.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2022 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" + android:ordering="together"> + <objectAnimator + android:propertyName="translationX" + android:valueFrom="32dp" + android:valueTo="0dp" + android:duration="600" + android:valueType="floatType" /> + <objectAnimator + android:propertyName="transitionAlpha" + android:valueFrom="0" + android:valueTo="1" + android:duration="167" + android:valueType="floatType" /> +</set>
\ No newline at end of file diff --git a/packages/SystemUI/res/anim/media_metadata_exit.xml b/packages/SystemUI/res/anim/media_metadata_exit.xml new file mode 100644 index 000000000000..0ee1171c3bf0 --- /dev/null +++ b/packages/SystemUI/res/anim/media_metadata_exit.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2022 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<set xmlns:android="http://schemas.android.com/apk/res/android" + android:ordering="together"> + <objectAnimator + android:propertyName="translationX" + android:valueFrom="0dp" + android:valueTo="-32dp" + android:duration="167" + android:valueType="floatType" /> + <objectAnimator + android:propertyName="transitionAlpha" + android:valueFrom="1" + android:valueTo="0" + android:duration="83" + android:startOffset="83" + android:valueType="floatType" /> +</set> diff --git a/packages/SystemUI/res/drawable/overlay_button_background.xml b/packages/SystemUI/res/drawable/overlay_button_background.xml index 0e8438c8a11d..c045048802f7 100644 --- a/packages/SystemUI/res/drawable/overlay_button_background.xml +++ b/packages/SystemUI/res/drawable/overlay_button_background.xml @@ -18,7 +18,7 @@ (clipboard text editor, long screenshots) --> <ripple xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" - android:color="?android:textColorPrimary"> + android:color="@color/overlay_button_ripple"> <item android:id="@android:id/background"> <inset android:insetTop="4dp" android:insetBottom="4dp"> <shape android:shape="rectangle"> diff --git a/packages/SystemUI/res/layout/fgs_manager_app_item.xml b/packages/SystemUI/res/layout/fgs_manager_app_item.xml index d034f4e512a3..30bce9d84489 100644 --- a/packages/SystemUI/res/layout/fgs_manager_app_item.xml +++ b/packages/SystemUI/res/layout/fgs_manager_app_item.xml @@ -26,7 +26,7 @@ android:id="@+id/fgs_manager_app_item_icon" android:layout_width="28dp" android:layout_height="28dp" - android:layout_marginRight="12dp" /> + android:layout_marginEnd="12dp" /> <LinearLayout android:layout_width="0dp" @@ -38,7 +38,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="start" - style="@style/TextAppearance.Dialog.Body" /> + style="@style/FgsManagerAppLabel" /> <TextView android:id="@+id/fgs_manager_app_item_duration" android:layout_width="match_parent" @@ -52,6 +52,6 @@ android:layout_width="wrap_content" android:layout_height="48dp" android:text="@string/fgs_manager_app_item_stop_button_label" - android:layout_marginLeft="12dp" + android:layout_marginStart="12dp" style="?android:attr/buttonBarNeutralButtonStyle" /> </LinearLayout> diff --git a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml index f72a8dc08c9c..5b961595fbd3 100644 --- a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml +++ b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml @@ -198,20 +198,29 @@ android:clickable="false" android:focusable="false"> - <FrameLayout + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="match_parent" android:layout_weight="1" + android:gravity="start|center_vertical" android:orientation="vertical" - android:clickable="false" - android:layout_width="wrap_content" - android:layout_height="match_parent"> + android:clickable="false"> <TextView android:id="@+id/wifi_toggle_title" android:text="@string/turn_on_wifi" android:layout_width="wrap_content" - android:layout_height="match_parent" + android:layout_height="wrap_content" android:gravity="start|center_vertical" android:textAppearance="@style/TextAppearance.InternetDialog"/> - </FrameLayout> + <TextView + android:id="@+id/wifi_toggle_summary" + android:text="@string/wifitrackerlib_admin_restricted_network" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="start|center_vertical" + android:textAppearance="@style/TextAppearance.InternetDialog.Secondary" + android:visibility="gone"/> + </LinearLayout> <FrameLayout android:layout_width="@dimen/settingslib_switch_track_width" diff --git a/packages/SystemUI/res/layout/media_output_list_item.xml b/packages/SystemUI/res/layout/media_output_list_item.xml index d39b0d53c743..b85ea598dbb4 100644 --- a/packages/SystemUI/res/layout/media_output_list_item.xml +++ b/packages/SystemUI/res/layout/media_output_list_item.xml @@ -33,7 +33,7 @@ android:layout_height="match_parent" android:background="@drawable/media_output_item_background" android:layout_gravity="center_vertical|start"> - <com.android.systemui.media.dialog.MediaOutputSeekbar + <SeekBar android:id="@+id/volume_seekbar" android:splitTrack="false" android:visibility="gone" @@ -119,15 +119,24 @@ android:importantForAccessibility="no" android:visibility="gone"/> + <LinearLayout + android:id="@+id/end_action_area" + android:visibility="gone" + android:orientation="vertical" + android:layout_width="48dp" + android:layout_height="64dp" + android:layout_gravity="right|center" + android:gravity="center_vertical"> <CheckBox android:id="@+id/check_box" android:layout_width="24dp" android:layout_height="24dp" android:layout_marginEnd="16dp" - android:layout_gravity="right|center" + android:layout_gravity="right" android:button="@drawable/ic_circle_check_box" android:visibility="gone" - android:clickable="false" /> + + </LinearLayout> </FrameLayout> </LinearLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/media_session_view.xml b/packages/SystemUI/res/layout/media_session_view.xml index b67b7bc3b92e..665edac65afc 100644 --- a/packages/SystemUI/res/layout/media_session_view.xml +++ b/packages/SystemUI/res/layout/media_session_view.xml @@ -63,8 +63,8 @@ <!-- App icon --> <com.android.internal.widget.CachingIconView android:id="@+id/icon" - android:layout_width="24dp" - android:layout_height="24dp" + android:layout_width="@dimen/qs_media_app_icon_size" + android:layout_height="@dimen/qs_media_app_icon_size" android:layout_marginStart="@dimen/qs_media_padding" android:layout_marginTop="@dimen/qs_media_padding" app:layout_constraintStart_toStartOf="parent" diff --git a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml index c3fc66952395..5510f24870bb 100644 --- a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml +++ b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml @@ -22,163 +22,150 @@ android:id="@+id/media_recommendations" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingStart="@dimen/qs_media_padding" - android:paddingEnd="@dimen/qs_media_padding" android:clipChildren="false" android:clipToPadding="false" android:forceHasOverlappingRendering="false" android:background="@drawable/qs_media_background" android:theme="@style/MediaPlayer"> - <androidx.constraintlayout.widget.Guideline - android:id="@+id/media_vertical_start_guideline" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="vertical" - app:layout_constraintGuide_percent="0.25" /> - - <androidx.constraintlayout.widget.Guideline - android:id="@+id/media_horizontal_center_guideline" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="horizontal" - app:layout_constraintGuide_percent="0.5" /> + <!-- This view just ensures the full media player is a certain height. --> + <View + android:id="@+id/sizing_view" + android:layout_width="match_parent" + android:layout_height="@dimen/qs_media_session_height_expanded" /> <com.android.internal.widget.CachingIconView android:id="@+id/recommendation_card_icon" - android:layout_width="@dimen/qs_media_icon_size" - android:layout_height="@dimen/qs_media_icon_size" + android:layout_width="@dimen/qs_media_app_icon_size" + android:layout_height="@dimen/qs_media_app_icon_size" + android:layout_marginStart="@dimen/qs_media_padding" android:layout_marginTop="@dimen/qs_media_padding" - android:src="@drawable/ic_headset" - style="@style/MediaPlayer.AppIcon" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toStartOf="@id/media_vertical_start_guideline" - app:layout_constraintHorizontal_bias="0"/> - - <TextView - android:id="@+id/recommendation_card_text" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:maxLines="1" - android:text="@string/controls_media_smartspace_rec_title" - android:fontFamily="google-sans-medium" - android:textDirection="locale" - android:textSize="@dimen/qq_aa_media_rec_header_text_size" - android:hyphenationFrequency="none" - app:layout_constraintTop_toBottomOf="@id/recommendation_card_icon" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toStartOf="@id/media_vertical_start_guideline" - app:layout_constraintHorizontal_bias="0"/> - - <View - android:id="@+id/recommendation_gradient_view" - android:layout_width="@dimen/qs_aa_media_gradient_bg_width" - android:layout_height="0dp" - android:clipToPadding="false" - android:clipChildren="false" - android:background="@drawable/qs_media_recommendation_bg_gradient" - app:layout_constraintTop_toTopOf="@id/recommendation_card_text" - app:layout_constraintBottom_toBottomOf="@id/recommendation_card_text" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toStartOf="@id/media_vertical_start_guideline" - app:layout_constraintHorizontal_bias="1"/> + app:layout_constraintTop_toTopOf="parent" /> <FrameLayout android:id="@+id/media_cover1_container" - android:layout_width="0dp" - android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed" - android:background="@drawable/qs_media_light_source"> + style="@style/MediaPlayer.Recommendation.AlbumContainer" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toTopOf="@+id/media_title1" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toStartOf="@id/media_cover2_container" + android:layout_marginEnd="@dimen/qs_media_rec_album_side_margin" + app:layout_constraintHorizontal_chainStyle="packed" + app:layout_constraintHorizontal_bias="1.0" + app:layout_constraintVertical_bias="0.5" + > <ImageView android:id="@+id/media_cover1" android:layout_width="match_parent" android:layout_height="match_parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" android:adjustViewBounds="true" android:background="@drawable/bg_smartspace_media_item" - style="@style/MediaPlayer.Album" + style="@style/MediaPlayer.Recommendation.Album" android:clipToOutline="true" android:scaleType="centerCrop"/> </FrameLayout> + <TextView + android:id="@+id/media_title1" + style="@style/MediaPlayer.Recommendation.Text.Title" + app:layout_constraintStart_toStartOf="@+id/media_cover1_container" + app:layout_constraintEnd_toEndOf="@+id/media_cover1_container" + app:layout_constraintTop_toBottomOf="@+id/media_cover1_container" + app:layout_constraintBottom_toTopOf="@+id/media_subtitle1" + /> + + <TextView + android:id="@+id/media_subtitle1" + style="@style/MediaPlayer.Recommendation.Text.Subtitle" + app:layout_constraintStart_toStartOf="@+id/media_cover1_container" + app:layout_constraintEnd_toEndOf="@+id/media_cover1_container" + app:layout_constraintTop_toBottomOf="@+id/media_title1" + app:layout_constraintBottom_toBottomOf="parent" + android:layout_marginBottom="@dimen/qs_media_padding" + /> + <FrameLayout android:id="@+id/media_cover2_container" - android:layout_width="0dp" - android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed" - android:background="@drawable/qs_media_light_source"> + style="@style/MediaPlayer.Recommendation.AlbumContainer" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toTopOf="@id/media_title2" + app:layout_constraintStart_toEndOf="@id/media_cover1_container" + app:layout_constraintEnd_toStartOf="@id/media_cover3_container" + android:layout_marginEnd="@dimen/qs_media_rec_album_side_margin" + app:layout_constraintVertical_bias="0.5" + > <ImageView android:id="@+id/media_cover2" android:layout_width="match_parent" android:layout_height="match_parent" android:adjustViewBounds="true" android:background="@drawable/bg_smartspace_media_item" - style="@style/MediaPlayer.Album" + style="@style/MediaPlayer.Recommendation.Album" android:clipToOutline="true" android:scaleType="centerCrop"/> </FrameLayout> + <TextView + android:id="@+id/media_title2" + style="@style/MediaPlayer.Recommendation.Text.Title" + app:layout_constraintStart_toStartOf="@+id/media_cover2_container" + app:layout_constraintEnd_toEndOf="@+id/media_cover2_container" + app:layout_constraintTop_toBottomOf="@+id/media_cover2_container" + app:layout_constraintBottom_toTopOf="@+id/media_subtitle2" + /> + + <TextView + android:id="@+id/media_subtitle2" + style="@style/MediaPlayer.Recommendation.Text.Subtitle" + app:layout_constraintStart_toStartOf="@+id/media_cover2_container" + app:layout_constraintEnd_toEndOf="@+id/media_cover2_container" + app:layout_constraintTop_toBottomOf="@+id/media_title2" + app:layout_constraintBottom_toBottomOf="parent" + android:layout_marginBottom="@dimen/qs_media_padding" + /> + <FrameLayout android:id="@+id/media_cover3_container" - android:layout_width="0dp" - android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed" - android:background="@drawable/qs_media_light_source"> + style="@style/MediaPlayer.Recommendation.AlbumContainer" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toTopOf="@id/media_title3" + app:layout_constraintStart_toEndOf="@id/media_cover2_container" + app:layout_constraintEnd_toEndOf="parent" + android:layout_marginEnd="@dimen/qs_media_padding" + app:layout_constraintVertical_bias="0.5" + > <ImageView android:id="@+id/media_cover3" android:layout_width="match_parent" android:layout_height="match_parent" android:adjustViewBounds="true" android:background="@drawable/bg_smartspace_media_item" - style="@style/MediaPlayer.Album" + style="@style/MediaPlayer.Recommendation.Album" android:clipToOutline="true" android:scaleType="centerCrop"/> </FrameLayout> - <FrameLayout - android:id="@+id/media_cover4_container" - android:layout_width="0dp" - android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed" - android:background="@drawable/qs_media_light_source"> - <ImageView - android:id="@+id/media_cover4" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:adjustViewBounds="true" - android:background="@drawable/bg_smartspace_media_item" - style="@style/MediaPlayer.Album" - android:clipToOutline="true" - android:scaleType="centerCrop"/> - </FrameLayout> - - <FrameLayout - android:id="@+id/media_cover5_container" - android:layout_width="0dp" - android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed" - android:background="@drawable/qs_media_light_source"> - <ImageView - android:id="@+id/media_cover5" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:adjustViewBounds="true" - android:background="@drawable/bg_smartspace_media_item" - style="@style/MediaPlayer.Album" - android:clipToOutline="true" - android:scaleType="centerCrop"/> - </FrameLayout> + <TextView + android:id="@+id/media_title3" + style="@style/MediaPlayer.Recommendation.Text.Title" + app:layout_constraintStart_toStartOf="@+id/media_cover3_container" + app:layout_constraintEnd_toEndOf="@+id/media_cover3_container" + app:layout_constraintTop_toBottomOf="@+id/media_cover3_container" + app:layout_constraintBottom_toTopOf="@+id/media_subtitle3" + /> - <FrameLayout - android:id="@+id/media_cover6_container" - android:layout_width="0dp" - android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed" - android:background="@drawable/qs_media_light_source"> - <ImageView - android:id="@+id/media_cover6" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:adjustViewBounds="true" - android:background="@drawable/bg_smartspace_media_item" - style="@style/MediaPlayer.Album" - android:clipToOutline="true" - android:scaleType="centerCrop"/> - </FrameLayout> + <TextView + android:id="@+id/media_subtitle3" + style="@style/MediaPlayer.Recommendation.Text.Subtitle" + app:layout_constraintStart_toStartOf="@+id/media_cover3_container" + app:layout_constraintEnd_toEndOf="@+id/media_cover3_container" + app:layout_constraintTop_toBottomOf="@+id/media_title3" + app:layout_constraintBottom_toBottomOf="parent" + android:layout_marginBottom="@dimen/qs_media_padding" + /> <!-- Long press menu --> <TextView @@ -273,4 +260,4 @@ android:text="@string/controls_media_dismiss_button" /> </FrameLayout> -</com.android.systemui.util.animation.TransitionLayout>
\ No newline at end of file +</com.android.systemui.util.animation.TransitionLayout> diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml index 7e8112a8885b..4f7d09963fc6 100644 --- a/packages/SystemUI/res/layout/notification_info.xml +++ b/packages/SystemUI/res/layout/notification_info.xml @@ -135,6 +135,15 @@ asked for it --> android:layout_height="wrap_content" style="@*android:style/TextAppearance.DeviceDefault.Notification" /> + <!-- Non configurable app/channel text. appears instead of @+id/interruptiveness_settings--> + <TextView + android:id="@+id/non_configurable_call_text" + android:text="@string/notification_unblockable_call_desc" + android:visibility="gone" + android:layout_width="match_parent" + android:layout_height="wrap_content" + style="@*android:style/TextAppearance.DeviceDefault.Notification" /> + <!-- Non configurable multichannel text. appears instead of @+id/interruptiveness_settings--> <TextView android:id="@+id/non_configurable_multichannel_text" diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml index 2c29f071dcbc..2fb6d6cb9bd5 100644 --- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml +++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml @@ -55,7 +55,7 @@ android:clipChildren="false" android:clipToPadding="false" android:focusable="true" - android:paddingBottom="24dp" + android:paddingBottom="@dimen/qqs_layout_padding_bottom" android:importantForAccessibility="yes"> </com.android.systemui.qs.QuickQSPanel> </RelativeLayout> diff --git a/packages/SystemUI/res/layout/rounded_corners_bottom.xml b/packages/SystemUI/res/layout/rounded_corners_bottom.xml deleted file mode 100644 index bb6d4bddf25a..000000000000 --- a/packages/SystemUI/res/layout/rounded_corners_bottom.xml +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -** Copyright 2020, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. ---> -<com.android.systemui.RegionInterceptingFrameLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/rounded_corners_bottom" - android:layout_width="match_parent" - android:layout_height="match_parent"> - <ImageView - android:id="@+id/left" - android:layout_width="12dp" - android:layout_height="12dp" - android:layout_gravity="left|bottom" - android:tint="#ff000000" - android:visibility="gone" - android:src="@drawable/rounded_corner_bottom"/> - - <ImageView - android:id="@+id/right" - android:layout_width="12dp" - android:layout_height="12dp" - android:tint="#ff000000" - android:visibility="gone" - android:layout_gravity="right|bottom" - android:src="@drawable/rounded_corner_bottom"/> - -</com.android.systemui.RegionInterceptingFrameLayout> diff --git a/packages/SystemUI/res/layout/rounded_corners_top.xml b/packages/SystemUI/res/layout/rounded_corners_top.xml deleted file mode 100644 index 46648c88d921..000000000000 --- a/packages/SystemUI/res/layout/rounded_corners_top.xml +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -** Copyright 2020, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. ---> -<com.android.systemui.RegionInterceptingFrameLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/rounded_corners_top" - android:layout_width="match_parent" - android:layout_height="match_parent"> - <ImageView - android:id="@+id/left" - android:layout_width="12dp" - android:layout_height="12dp" - android:layout_gravity="left|top" - android:tint="#ff000000" - android:visibility="gone" - android:src="@drawable/rounded_corner_top"/> - - <ImageView - android:id="@+id/right" - android:layout_width="12dp" - android:layout_height="12dp" - android:tint="#ff000000" - android:visibility="gone" - android:layout_gravity="right|top" - android:src="@drawable/rounded_corner_top"/> - -</com.android.systemui.RegionInterceptingFrameLayout> diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index ecc52d3ad049..e56a810fc1f1 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -805,8 +805,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"Onderbreek"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"Vorige snit"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"Volgende snit"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"Koppel tans"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Speel"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Maak <xliff:g id="APP_LABEL">%1$s</xliff:g> oop"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Speel <xliff:g id="SONG_NAME">%1$s</xliff:g> deur <xliff:g id="ARTIST_NAME">%2$s</xliff:g> vanaf <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 6b7e3018065d..e9b2a1c046f8 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -805,8 +805,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"ላፍታ አቁም"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"ቀዳሚ ትራክ"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"ቀጣይ ትራክ"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"በመገናኘት ላይ"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"አጫውት"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ክፈት"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="SONG_NAME">%1$s</xliff:g> በ<xliff:g id="ARTIST_NAME">%2$s</xliff:g> ከ<xliff:g id="APP_LABEL">%3$s</xliff:g> ያጫውቱ"</string> diff --git a/packages/SystemUI/res/values-as-ldrtl/strings.xml b/packages/SystemUI/res/values-as-ldrtl/strings.xml index adee93aa20d2..f017d0c967e8 100644 --- a/packages/SystemUI/res/values-as-ldrtl/strings.xml +++ b/packages/SystemUI/res/values-as-ldrtl/strings.xml @@ -19,5 +19,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"তাত্ক্ষণিকভাৱে আনটো এপ্ ব্য়ৱহাৰ কৰিবলৈ বাওঁফালে টানক"</string> + <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"তাত্ক্ষণিকভাৱে আনটো এপ্ ব্যৱহাৰ কৰিবলৈ বাওঁফালে টানক"</string> </resources> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index acc4acf3eb7c..ce58c7cc6cb1 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -805,8 +805,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"পজ কৰক"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"পূৰ্বৱৰ্তী ট্ৰেক"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"পৰৱৰ্তী ট্ৰেক"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"সংযোগ কৰি থকা হৈছে"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"প্লে’ কৰক"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> খোলক"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g>ত <xliff:g id="ARTIST_NAME">%2$s</xliff:g>ৰ <xliff:g id="SONG_NAME">%1$s</xliff:g> গীতটো প্লে’ কৰক"</string> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index 5ad92076eac8..5a62066936d8 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -805,8 +805,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"Durdurun"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"Əvvəlki trek"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"Növbəti trek"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"Qoşulur"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Oxudun"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> tətbiqini açın"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> tərəfindən <xliff:g id="SONG_NAME">%1$s</xliff:g> mahnısını <xliff:g id="APP_LABEL">%3$s</xliff:g> tətbiqindən oxudun"</string> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index b539c4733a03..a5ad4f71185d 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -811,8 +811,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"Pauziraj"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"Prethodna pesma"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"Sledeća pesma"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"Povezuje se"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Pusti"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Otvorite <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Pustite <xliff:g id="SONG_NAME">%1$s</xliff:g> izvođača <xliff:g id="ARTIST_NAME">%2$s</xliff:g> iz aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index 6fabe3fd035a..67e838bfa8cb 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -27,7 +27,7 @@ <string name="invalid_charger_title" msgid="938685362320735167">"Зареждането през USB не е възможно"</string> <string name="invalid_charger_text" msgid="2339310107232691577">"Използвайте оригиналното зарядно устройство"</string> <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Да се включи ли режимът за запазване на батерията?"</string> - <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Всичко за режима за запазване на батерията"</string> + <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"За режима за запазване на батерията"</string> <string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Включване"</string> <string name="battery_saver_start_action" msgid="8353766979886287140">"Включване"</string> <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Не, благодаря"</string> @@ -732,8 +732,8 @@ <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофона"</string> <string name="music_controls_no_title" msgid="4166497066552290938">"Няма заглавие"</string> <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Режим на готовност"</string> - <string name="magnification_window_title" msgid="4863914360847258333">"Прозорец за ниво на мащаба"</string> - <string name="magnification_controls_title" msgid="8421106606708891519">"Контроли за прозореца за ниво на мащаба"</string> + <string name="magnification_window_title" msgid="4863914360847258333">"Прозорец за увеличение"</string> + <string name="magnification_controls_title" msgid="8421106606708891519">"Контроли за прозореца за увеличение"</string> <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Увеличаване на мащаба"</string> <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Намаляване на мащаба"</string> <string name="accessibility_control_move_up" msgid="6622825494014720136">"Преместване нагоре"</string> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index b3f20da1ae55..d763748d504f 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -570,7 +570,7 @@ <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"বিজ্ঞপ্তি"</string> <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"কীবোর্ড শর্টকাট"</string> <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"কীবোর্ড লে-আউট পাল্টান"</string> - <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"অ্যাপ্লিকেশানগুলি"</string> + <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"অ্যাপ্লিকেশন"</string> <string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"সহযোগিতা"</string> <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"ব্রাউজার"</string> <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"পরিচিতি"</string> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index fad3ec8673b0..11b9f429c301 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -27,7 +27,7 @@ <string name="invalid_charger_title" msgid="938685362320735167">"Punjenje putem USB-a nije moguće"</string> <string name="invalid_charger_text" msgid="2339310107232691577">"Koristite punjač koji ste dobili uz uređaj"</string> <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Uključiti Uštedu baterije?"</string> - <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Informacije o Uštedi baterije"</string> + <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"O Uštedi baterije"</string> <string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Uključi"</string> <string name="battery_saver_start_action" msgid="8353766979886287140">"Uključi"</string> <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Ne, hvala"</string> @@ -453,7 +453,7 @@ <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"Pozivi i obavještenja će zvoniti jačinom (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"Podešavač za korisnički interfejs sistema"</string> <string name="status_bar" msgid="4357390266055077437">"Statusna traka"</string> - <string name="demo_mode" msgid="263484519766901593">"Način rada za demonstraciju Sistemskog UI-a"</string> + <string name="demo_mode" msgid="263484519766901593">"Demo način rada Sistemskog UI-ja"</string> <string name="enable_demo_mode" msgid="3180345364745966431">"Omogući način rada za demonstraciju"</string> <string name="show_demo_mode" msgid="3677956462273059726">"Prikaži način rada za demonstraciju"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"Ethernet"</string> @@ -811,8 +811,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"Pauziranje"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"Prethodna numera"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"Sljedeća numera"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"Povezivanje"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Pokrenite"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Otvorite aplikaciju <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Reproducirajte pjesmu <xliff:g id="SONG_NAME">%1$s</xliff:g> izvođača <xliff:g id="ARTIST_NAME">%2$s</xliff:g> pomoću aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index b51ae5fa9ba9..8118f54b3aa0 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -805,8 +805,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"Pausar"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"Pista anterior"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"Siguiente pista"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"Conectando"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Reproducir"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Abrir <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Poner <xliff:g id="SONG_NAME">%1$s</xliff:g> de <xliff:g id="ARTIST_NAME">%2$s</xliff:g> en <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string> @@ -905,7 +904,7 @@ <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Por ahora no se conectará automáticamente a redes Wi-Fi"</string> <string name="see_all_networks" msgid="3773666844913168122">"Ver todo"</string> <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Para cambiar de red, desconecta el cable Ethernet"</string> - <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Para mejorar la experiencia con el dispositivo, las aplicaciones y los servicios podrán buscar redes Wi-Fi en cualquier momento, aunque la conexión Wi-Fi esté desactivada. Puedes cambiarlo en los ajustes de búsqueda de redes Wi-Fi. "<annotation id="link">"Cambiar"</annotation></string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Para mejorar la experiencia con el dispositivo, las aplicaciones y los servicios podrán buscar redes Wi-Fi en cualquier momento, aunque la conexión Wi-Fi esté desactivada. Puedes cambiar esto en los ajustes de búsqueda de redes Wi-Fi. "<annotation id="link">"Cambiar"</annotation></string> <string name="turn_off_airplane_mode" msgid="8425587763226548579">"Desactivar modo avión"</string> <string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> quiere añadir el siguiente recuadro a ajustes rápidos"</string> <string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Añadir recuadro"</string> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 6d7bf05539fb..dd4c43f0464e 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -805,8 +805,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"توقف موقت"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"آهنگ قبلی"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"آهنگ بعدی"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"درحال اتصال"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"پخش"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"باز کردن <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="SONG_NAME">%1$s</xliff:g> از <xliff:g id="ARTIST_NAME">%2$s</xliff:g> را ازطریق <xliff:g id="APP_LABEL">%3$s</xliff:g> پخش کنید"</string> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 2822eb28fbfd..bac2f5aed928 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -383,7 +383,7 @@ <string name="monitoring_title_device_owned" msgid="7029691083837606324">"डिवाइस मैनेजमेंट"</string> <string name="monitoring_subtitle_vpn" msgid="800485258004629079">"वीपीएन"</string> <string name="monitoring_subtitle_network_logging" msgid="2444199331891219596">"नेटवर्क लॉगिंग"</string> - <string name="monitoring_subtitle_ca_certificate" msgid="8588092029755175800">"CA प्रमाणपत्र"</string> + <string name="monitoring_subtitle_ca_certificate" msgid="8588092029755175800">"CA सर्टिफ़िकेट"</string> <string name="monitoring_button_view_policies" msgid="3869724835853502410">"नीतियां देखें"</string> <string name="monitoring_button_view_controls" msgid="8316440345340701117">"कंट्रोल देखें"</string> <string name="monitoring_description_named_management" msgid="505833016545056036">"इस डिवाइस का मालिकाना हक <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> के पास है.\n\nआपके संगठन का आईटी एडमिन कुछ चीज़ों की निगरानी और उन्हें प्रबंधित कर सकता है, जैसे कि सेटिंग, कॉर्पोरेट ऐक्सेस, ऐप्लिकेशन, आपके डिवाइस से जुड़ा डेटा, और आपके डिवाइस की जगह की जानकारी.\n\nज़्यादा जानकारी के लिए, अपने आईटी एडमिन से संपर्क करें."</string> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index ef31620c78fb..2d03d51356c5 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -27,7 +27,7 @@ <string name="invalid_charger_title" msgid="938685362320735167">"Punjenje putem USB-a nije moguće"</string> <string name="invalid_charger_text" msgid="2339310107232691577">"Koristite punjač koji ste dobili s uređajem"</string> <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Uključiti štednju baterije?"</string> - <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"O Štednji baterije"</string> + <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"O štednji baterije"</string> <string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Uključi"</string> <string name="battery_saver_start_action" msgid="8353766979886287140">"Uključi"</string> <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"Ne, hvala"</string> @@ -811,8 +811,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"Pauziraj"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"Prethodni zapis"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"Sljedeći zapis"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"Povezivanje"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Reprodukcija"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Otvori <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Pustite <xliff:g id="SONG_NAME">%1$s</xliff:g>, <xliff:g id="ARTIST_NAME">%2$s</xliff:g> putem aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 8c7569c662d6..2e879011f5f7 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -568,7 +568,7 @@ <string name="keyboard_shortcut_group_system_recents" msgid="8628108256824616927">"Terbaru"</string> <string name="keyboard_shortcut_group_system_back" msgid="1055709713218453863">"Kembali"</string> <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifikasi"</string> - <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Pintasan Keyboard"</string> + <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Pintasan keyboard"</string> <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Ganti tata letak keyboard"</string> <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplikasi"</string> <string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Bantuan"</string> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 9b2178aaf2f7..d2e0f0a92239 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -27,7 +27,7 @@ <string name="invalid_charger_title" msgid="938685362320735167">"Impossibile ricaricare tramite USB"</string> <string name="invalid_charger_text" msgid="2339310107232691577">"Utilizza il caricabatterie fornito in dotazione con il dispositivo"</string> <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Attivare il risparmio energetico?"</string> - <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Informazioni su Risparmio energetico"</string> + <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Informazioni sul risparmio energetico"</string> <string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Attiva"</string> <string name="battery_saver_start_action" msgid="8353766979886287140">"Attiva"</string> <string name="battery_saver_dismiss_action" msgid="7199342621040014738">"No, grazie"</string> @@ -805,8 +805,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"Metti in pausa"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"Traccia precedente"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"Traccia successiva"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"Connessione in corso…"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Riproduci"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Apri <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Riproduci <xliff:g id="SONG_NAME">%1$s</xliff:g> di <xliff:g id="ARTIST_NAME">%2$s</xliff:g> da <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string> @@ -905,7 +904,7 @@ <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Connessione automatica rete Wi-Fi non attiva al momento"</string> <string name="see_all_networks" msgid="3773666844913168122">"Mostra tutte"</string> <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Per cambiare rete, scollega il cavo Ethernet"</string> - <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Per migliorare l\'esperienza con il dispositivo, le app e i servizi possono continuare a cercare reti Wi-Fi in qualsiasi momento, anche quando la connessione Wi-Fi non è attiva. Puoi modificare questa preferenza nelle impostazioni relative alla ricerca di reti Wi-Fi. "<annotation id="link">"Cambia"</annotation></string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Per migliorare l\'esperienza con il dispositivo, le app e i servizi possono continuare a cercare reti Wi-Fi in qualsiasi momento, anche quando la connessione Wi-Fi non è attiva. Puoi modificare questa preferenza nelle impostazioni relative alla ricerca di reti Wi-Fi. "<annotation id="link">"Modifica"</annotation></string> <string name="turn_off_airplane_mode" msgid="8425587763226548579">"Disattiva la modalità aereo"</string> <string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> vuole aggiungere il seguente riquadro alle Impostazioni rapide"</string> <string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Aggiungi riquadro"</string> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index 69f4ba13ff78..d675b7ce1fae 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -805,8 +805,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"პაუზა"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"წინა ჩანაწერი"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"შემდეგი ჩანაწერი"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"მიმდინარეობს დაკავშირება"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"დაკვრა"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"გახსენით <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"დაუკარით <xliff:g id="SONG_NAME">%1$s</xliff:g>, <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, <xliff:g id="APP_LABEL">%3$s</xliff:g>-დან"</string> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index a5d8fd950df1..50b3215161f9 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -805,8 +805,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"ຢຸດຊົ່ວຄາວ"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"ເພງກ່ອນໜ້າ"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"ເພງຕໍ່ໄປ"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"ກຳລັງເຊື່ອມຕໍ່"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"ຫຼິ້ນ"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"ເປີດ <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"ຫຼິ້ນ <xliff:g id="SONG_NAME">%1$s</xliff:g> ໂດຍ <xliff:g id="ARTIST_NAME">%2$s</xliff:g> ຈາກ <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index b58338c813f6..360966342c29 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -564,7 +564,7 @@ <string name="keyboard_key_numpad_template" msgid="7316338238459991821">"Numpad <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="notif_inline_reply_remove_attachment_description" msgid="7954075334095405429">"Отстрани го прилогот"</string> <string name="keyboard_shortcut_group_system" msgid="1583416273777875970">"Систем"</string> - <string name="keyboard_shortcut_group_system_home" msgid="7465138628692109907">"Почетна страница"</string> + <string name="keyboard_shortcut_group_system_home" msgid="7465138628692109907">"Почетен екран"</string> <string name="keyboard_shortcut_group_system_recents" msgid="8628108256824616927">"Неодамнешни"</string> <string name="keyboard_shortcut_group_system_back" msgid="1055709713218453863">"Назад"</string> <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Известувања"</string> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index be345acb9e27..31d33d7d991f 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -564,7 +564,7 @@ <string name="keyboard_key_numpad_template" msgid="7316338238459991821">"നംപാഡ് <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="notif_inline_reply_remove_attachment_description" msgid="7954075334095405429">"അറ്റാച്ച്മെന്റ് നീക്കം ചെയ്യുക"</string> <string name="keyboard_shortcut_group_system" msgid="1583416273777875970">"സിസ്റ്റം"</string> - <string name="keyboard_shortcut_group_system_home" msgid="7465138628692109907">"വീട്"</string> + <string name="keyboard_shortcut_group_system_home" msgid="7465138628692109907">"ഹോം"</string> <string name="keyboard_shortcut_group_system_recents" msgid="8628108256824616927">"പുതിയവ"</string> <string name="keyboard_shortcut_group_system_back" msgid="1055709713218453863">"മടങ്ങുക"</string> <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"അറിയിപ്പുകൾ"</string> @@ -805,8 +805,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"താൽക്കാലികമായി നിർത്തുക"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"മുമ്പത്തെ ട്രാക്ക്"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"അടുത്ത ട്രാക്ക്"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"കണക്റ്റ് ചെയ്യുന്നു"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"പ്ലേ ചെയ്യുക"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> തുറക്കുക"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> എന്ന ആർട്ടിസ്റ്റിന്റെ <xliff:g id="SONG_NAME">%1$s</xliff:g> എന്ന ഗാനം <xliff:g id="APP_LABEL">%3$s</xliff:g> ആപ്പിൽ പ്ലേ ചെയ്യുക"</string> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 45211c45e28a..2f3a089b3895 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -805,8 +805,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"Түр зогсоох"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"Өмнөх бичлэг"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"Дараагийн бичлэг"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"Холбогдож байна"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Тоглуулах"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g>-г нээх"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g>-н <xliff:g id="SONG_NAME">%1$s</xliff:g>-г <xliff:g id="APP_LABEL">%3$s</xliff:g> дээр тоглуулах"</string> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index d431a2b8879b..9e2b73e1faed 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -563,7 +563,7 @@ <string name="keyboard_key_num_lock" msgid="7209960042043090548">"Num Lock"</string> <string name="keyboard_key_numpad_template" msgid="7316338238459991821">"Numpad <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="notif_inline_reply_remove_attachment_description" msgid="7954075334095405429">"अटॅचमेंट काढा"</string> - <string name="keyboard_shortcut_group_system" msgid="1583416273777875970">"सिस्टम"</string> + <string name="keyboard_shortcut_group_system" msgid="1583416273777875970">"सिस्टीम"</string> <string name="keyboard_shortcut_group_system_home" msgid="7465138628692109907">"होम"</string> <string name="keyboard_shortcut_group_system_recents" msgid="8628108256824616927">"अलीकडील"</string> <string name="keyboard_shortcut_group_system_back" msgid="1055709713218453863">"परत"</string> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 9bab5cb38d1e..046025e40237 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -805,8 +805,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"Jeda"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"Lagu sebelumnya"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"Lagu seterusnya"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"Menyambung"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Main"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Buka <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Mainkan <xliff:g id="SONG_NAME">%1$s</xliff:g> oleh <xliff:g id="ARTIST_NAME">%2$s</xliff:g> daripada <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml index 3a638b1e5098..dc2bee56373c 100644 --- a/packages/SystemUI/res/values-night/colors.xml +++ b/packages/SystemUI/res/values-night/colors.xml @@ -59,7 +59,6 @@ <color name="global_actions_alert_text">@color/GM2_red_300</color> <!-- Floating overlay actions --> - <color name="overlay_button_ripple">#42FFFFFF</color> <color name="overlay_background_protection_start">#80000000</color> <!-- 50% black --> <!-- Media --> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index 649230397d1f..d06fd267abda 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -805,8 +805,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"ਰੋਕੋ"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"ਪਿਛਲਾ ਟਰੈਕ"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"ਅਗਲਾ ਟਰੈਕ"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"ਕਨੈਕਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"ਚਲਾਓ"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ਖੋਲ੍ਹੋ"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> ਤੋਂ <xliff:g id="ARTIST_NAME">%2$s</xliff:g> ਦਾ <xliff:g id="SONG_NAME">%1$s</xliff:g> ਚਲਾਓ"</string> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 71964715cf23..c9e8a297bf8c 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -817,8 +817,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"Wstrzymaj"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"Poprzedni utwór"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"Następny utwór"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"Łączę"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Odtwórz"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Otwórz aplikację <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Odtwórz utwór <xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="ARTIST_NAME">%2$s</xliff:g>) w aplikacji <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-pl/tiles_states_strings.xml b/packages/SystemUI/res/values-pl/tiles_states_strings.xml index aae48c815d69..f5d8f1fe815d 100644 --- a/packages/SystemUI/res/values-pl/tiles_states_strings.xml +++ b/packages/SystemUI/res/values-pl/tiles_states_strings.xml @@ -87,9 +87,9 @@ <item msgid="2075645297847971154">"Włączony"</item> </string-array> <string-array name="tile_states_color_correction"> - <item msgid="2840507878437297682">"Brak dostępu"</item> - <item msgid="1909756493418256167">"Wyłączono"</item> - <item msgid="4531508423703413340">"Włączono"</item> + <item msgid="2840507878437297682">"Niedostępna"</item> + <item msgid="1909756493418256167">"Wyłączona"</item> + <item msgid="4531508423703413340">"Włączona"</item> </string-array> <string-array name="tile_states_inversion"> <item msgid="3638187931191394628">"Niedostępne"</item> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index 5ad42728d5e7..d8519df6d3a7 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -52,7 +52,7 @@ <string name="usb_debugging_always" msgid="4003121804294739548">"Permitir sempre a partir deste computador"</string> <string name="usb_debugging_allow" msgid="1722643858015321328">"Permitir"</string> <string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"Depuração USB não permitida"</string> - <string name="usb_debugging_secondary_user_message" msgid="3740347841470403244">"O utilizador com sessão iniciada atualmente neste dispositivo não pode ativar a depuração USB. Para utilizar esta funcionalidade, mude para o utilizador principal."</string> + <string name="usb_debugging_secondary_user_message" msgid="3740347841470403244">"O utilizador com sessão iniciada atualmente neste dispositivo não pode ativar a depuração USB. Para usar esta funcionalidade, mude para o utilizador principal."</string> <string name="hdmi_cec_set_menu_language_title" msgid="1259765420091503742">"Quer alterar o idioma do sistema para <xliff:g id="LANGUAGE">%1$s</xliff:g>?"</string> <string name="hdmi_cec_set_menu_language_description" msgid="8176716678074126619">"Alteração do idioma do sistema solicitada por outro dispositivo"</string> <string name="hdmi_cec_set_menu_language_accept" msgid="2513689457281009578">"Alterar idioma"</string> @@ -62,7 +62,7 @@ <string name="wifi_debugging_always" msgid="2968383799517975155">"Permitir sempre nesta rede"</string> <string name="wifi_debugging_allow" msgid="4573224609684957886">"Permitir"</string> <string name="wifi_debugging_secondary_user_title" msgid="2493201475880517725">"Depuração sem fios não permitida"</string> - <string name="wifi_debugging_secondary_user_message" msgid="4492383073970079751">"O utilizador com sessão iniciada atualmente neste dispositivo não pode ativar a depuração sem fios. Para utilizar esta funcionalidade, mude para o utilizador principal."</string> + <string name="wifi_debugging_secondary_user_message" msgid="4492383073970079751">"O utilizador com sessão iniciada atualmente neste dispositivo não pode ativar a depuração sem fios. Para usar esta funcionalidade, mude para o utilizador principal."</string> <string name="usb_contaminant_title" msgid="894052515034594113">"Porta USB desativada"</string> <string name="usb_contaminant_message" msgid="7730476585174719805">"Para proteger o dispositivo contra líquidos ou resíduos, a porta USB está desativada e não irá detetar quaisquer acessórios.\n\nSerá notificado quando for seguro utilizar a porta USB novamente."</string> <string name="usb_port_enabled" msgid="531823867664717018">"Porta USB ativada para detetar carregadores e acessórios"</string> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 6af03885137b..d7d66220f079 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -811,8 +811,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"Întrerupeți"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"Melodia anterioară"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"Melodia următoare"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"Se conectează"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Redați"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Deschideți <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Redați <xliff:g id="SONG_NAME">%1$s</xliff:g> de la <xliff:g id="ARTIST_NAME">%2$s</xliff:g> în <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 1e2949e2ce6e..22f0a0499ecd 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -817,8 +817,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"Pozastaviť"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"Predchádzajúca skladba"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"Ďalšia skladba"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"Pripája sa"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Prehrať"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Otvoriť <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Prehrať skladbu <xliff:g id="SONG_NAME">%1$s</xliff:g> od interpreta <xliff:g id="ARTIST_NAME">%2$s</xliff:g> z aplikácie <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index 8ff71a419880..5b06c838278e 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -817,8 +817,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"Začasno zaustavi"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"Prejšnja skladba"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"Naslednja skladba"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"Vzpostavljanje povezave"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Predvajaj"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Odpri aplikacijo <xliff:g id="APP_LABEL">%1$s</xliff:g>."</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Predvajaj skladbo <xliff:g id="SONG_NAME">%1$s</xliff:g> izvajalca <xliff:g id="ARTIST_NAME">%2$s</xliff:g> iz aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>."</string> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index e1cd04ffe1e4..4f4ffabe545a 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -811,8 +811,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"Паузирај"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"Претходна песма"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"Следећа песма"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"Повезује се"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Пусти"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Отворите <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Пустите <xliff:g id="SONG_NAME">%1$s</xliff:g> извођача <xliff:g id="ARTIST_NAME">%2$s</xliff:g> из апликације <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-sw600dp-port/dimens.xml b/packages/SystemUI/res/values-sw600dp-port/dimens.xml index f5c0509dbf5b..589d12f95f45 100644 --- a/packages/SystemUI/res/values-sw600dp-port/dimens.xml +++ b/packages/SystemUI/res/values-sw600dp-port/dimens.xml @@ -20,4 +20,6 @@ <dimen name="keyguard_clock_top_margin">40dp</dimen> <dimen name="keyguard_status_view_bottom_margin">40dp</dimen> <dimen name="bouncer_user_switcher_y_trans">20dp</dimen> + + <dimen name="qqs_layout_padding_bottom">16dp</dimen> </resources> diff --git a/packages/SystemUI/res/values-sw720dp-land/dimens.xml b/packages/SystemUI/res/values-sw720dp-land/dimens.xml index 4d4f5205754f..33d6f19b35d0 100644 --- a/packages/SystemUI/res/values-sw720dp-land/dimens.xml +++ b/packages/SystemUI/res/values-sw720dp-land/dimens.xml @@ -18,8 +18,8 @@ --> <resources> <dimen name="controls_padding_horizontal">205dp</dimen> - <dimen name="split_shade_notifications_scrim_margin_bottom">16dp</dimen> - <dimen name="notification_panel_margin_bottom">56dp</dimen> + <dimen name="split_shade_notifications_scrim_margin_bottom">24dp</dimen> + <dimen name="notification_panel_margin_bottom">64dp</dimen> <dimen name="keyguard_split_shade_top_margin">72dp</dimen> diff --git a/packages/SystemUI/res/values-sw720dp-port/dimens.xml b/packages/SystemUI/res/values-sw720dp-port/dimens.xml index 44f8f3aee9ab..fc12d418d218 100644 --- a/packages/SystemUI/res/values-sw720dp-port/dimens.xml +++ b/packages/SystemUI/res/values-sw720dp-port/dimens.xml @@ -25,6 +25,8 @@ <dimen name="keyguard_status_view_bottom_margin">80dp</dimen> <dimen name="bouncer_user_switcher_y_trans">90dp</dimen> + <dimen name="qqs_layout_padding_bottom">40dp</dimen> + <dimen name="notification_panel_margin_horizontal">96dp</dimen> <dimen name="notification_side_paddings">40dp</dimen> <dimen name="notification_section_divider_height">16dp</dimen> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index 111da21a8a21..cbdc9e027634 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -805,8 +805,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"இடைநிறுத்து"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"முந்தைய டிராக்"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"அடுத்த டிராக்"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"இணைக்கிறது"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"இயக்குதல்"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ஆப்ஸைத் திறங்கள்"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> இன் <xliff:g id="SONG_NAME">%1$s</xliff:g> பாடலை <xliff:g id="APP_LABEL">%3$s</xliff:g> ஆப்ஸில் பிளேசெய்"</string> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index e76253a578b4..08e9c2fcc99a 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -805,8 +805,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"పాజ్ చేయండి"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"మునుపటి ట్రాక్"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"తర్వాతి ట్రాక్"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"కనెక్ట్ అవుతోంది"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"ప్లే చేయండి"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g>ను తెరవండి"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> నుండి <xliff:g id="ARTIST_NAME">%2$s</xliff:g> పాడిన <xliff:g id="SONG_NAME">%1$s</xliff:g>ను ప్లే చేయండి"</string> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index df36f46754e5..5db1ee3bd404 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -907,7 +907,7 @@ <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ตัดการเชื่อมต่ออีเทอร์เน็ตเพื่อสลับเครือข่าย"</string> <string name="wifi_scan_notify_message" msgid="3753839537448621794">"เพื่อปรับปรุงประสบการณ์การใช้อุปกรณ์ แอปและบริการต่างๆ จะยังคงสแกนหาเครือข่าย Wi‑Fi ได้ทุกเมื่อแม้ว่า Wi‑Fi จะปิดอยู่ คุณเปลี่ยนตัวเลือกนี้ได้ในการตั้งค่าการสแกนหา Wi-Fi "<annotation id="link">"เปลี่ยนการตั้งค่า"</annotation></string> <string name="turn_off_airplane_mode" msgid="8425587763226548579">"ปิดโหมดบนเครื่องบิน"</string> - <string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> ต้องการเพิ่มชิ้นส่วนต่อไปนี้ในการตั้งค่าด่วน"</string> + <string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> ต้องการเพิ่มองค์ประกอบต่อไปนี้ในการตั้งค่าด่วน"</string> <string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"เพิ่มชิ้นส่วน"</string> <string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"ไม่ต้องเพิ่มชิ้นส่วน"</string> <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"เลือกผู้ใช้"</string> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 4c4e49bac892..942416277779 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -905,7 +905,7 @@ <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Şu anda kablosuz ağa otomatik olarak bağlanılamıyor"</string> <string name="see_all_networks" msgid="3773666844913168122">"Tümünü göster"</string> <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Ağ değiştirmek için ethernet bağlantısını kesin"</string> - <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Uygulamalar ve hizmetler, cihaz deneyimini iyileştirmek için Kablosuz özelliği kapalı bile olsa kablosuz ağlar herhangi bir zamanda tarayabilir. Bunu kablosuz ağ taraması ayarlarından değiştirebilirsiniz. "<annotation id="link">"Değiştir"</annotation></string> + <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Uygulamalar ve hizmetler, cihaz deneyimini iyileştirmek için Kablosuz özelliği kapalı bile olsa kablosuz ağları herhangi bir zamanda tarayabilir. Bunu kablosuz ağ taraması ayarlarından değiştirebilirsiniz. "<annotation id="link">"Değiştir"</annotation></string> <string name="turn_off_airplane_mode" msgid="8425587763226548579">"Uçak modunu kapat"</string> <string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> aşağıdaki kartı Hızlı Ayarlar\'a eklemek istiyor"</string> <string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Kart ekle"</string> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index c0f12bdf8157..a2ce6bebb823 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -805,8 +805,7 @@ <string name="controls_media_button_pause" msgid="8614887780950376258">"Pauza"</string> <string name="controls_media_button_prev" msgid="8126822360056482970">"Avvalgi trek"</string> <string name="controls_media_button_next" msgid="6662636627525947610">"Keyingi trek"</string> - <!-- no translation found for controls_media_button_connecting (3138354625847598095) --> - <skip /> + <string name="controls_media_button_connecting" msgid="3138354625847598095">"Ulanmoqda"</string> <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Ijro"</string> <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ilovasini ochish"</string> <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> ilovasida ijro etish: <xliff:g id="SONG_NAME">%1$s</xliff:g> – <xliff:g id="ARTIST_NAME">%2$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 15a32fe37409..b77e008dc48e 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -21,8 +21,8 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="4811759950673118541">"系统界面"</string> <string name="battery_low_title" msgid="5319680173344341779">"要开启省电模式吗?"</string> - <string name="battery_low_description" msgid="3282977755476423966">"您的电池还剩 <xliff:g id="PERCENTAGE">%s</xliff:g> 的电量。省电模式会开启深色主题,限制后台活动并将通知延迟。"</string> - <string name="battery_low_intro" msgid="5148725009653088790">"省电模式会开启深色主题,限制后台活动并将通知延迟。"</string> + <string name="battery_low_description" msgid="3282977755476423966">"您的电池还剩 <xliff:g id="PERCENTAGE">%s</xliff:g> 的电量。省电模式会开启深色主题、限制后台活动,并将通知延迟。"</string> + <string name="battery_low_intro" msgid="5148725009653088790">"省电模式会开启深色主题、限制后台活动,并将通知延迟。"</string> <string name="battery_low_percent_format" msgid="4276661262843170964">"剩余<xliff:g id="PERCENTAGE">%s</xliff:g>"</string> <string name="invalid_charger_title" msgid="938685362320735167">"无法通过 USB 充电"</string> <string name="invalid_charger_text" msgid="2339310107232691577">"使用设备随附的充电器"</string> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index f2ddf9e645b6..ae5b8d8ae451 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -288,9 +288,6 @@ <!-- Enable the default volume level warning dialog --> <bool name="enable_safety_warning">true</bool> - <!-- Whether to show operator name in the status bar --> - <bool name="config_showOperatorNameInStatusBar">false</bool> - <!-- Whether to show the full screen user switcher. --> <bool name="config_enableFullscreenUserSwitcher">false</bool> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 101db839336e..4a8fd1b00dde 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -37,10 +37,10 @@ <!-- Size of the nav bar edge panels, should be greater to the edge sensitivity + the drag threshold --> - <dimen name="navigation_edge_panel_width">70dp</dimen> + <dimen name="navigation_edge_panel_width">105dp</dimen> <!-- Padding at the end of the navigation panel to allow the arrow not to be clipped off --> <dimen name="navigation_edge_panel_padding">8dp</dimen> - <dimen name="navigation_edge_panel_height">96dp</dimen> + <dimen name="navigation_edge_panel_height">268dp</dimen> <!-- The threshold to drag to trigger the edge action --> <dimen name="navigation_edge_action_drag_threshold">16dp</dimen> <!-- The threshold to progress back animation for edge swipe --> @@ -474,6 +474,7 @@ <dimen name="qs_brightness_margin_top">8dp</dimen> <dimen name="qs_brightness_margin_bottom">24dp</dimen> <dimen name="qqs_layout_margin_top">16dp</dimen> + <dimen name="qqs_layout_padding_bottom">24dp</dimen> <dimen name="qs_customize_internal_side_paddings">8dp</dimen> <dimen name="qs_icon_size">20dp</dimen> @@ -560,6 +561,9 @@ <!-- The height of the gap between adjacent notification sections. --> <dimen name="notification_section_divider_height">@dimen/notification_side_paddings</dimen> + <!-- The height of the gap between adjacent notification sections on lockscreen. --> + <dimen name="notification_section_divider_height_lockscreen">4dp</dimen> + <!-- Size of the face pile shown on one-line (children of a group) conversation notifications --> <dimen name="conversation_single_line_face_pile_size">24dp</dimen> @@ -958,7 +962,6 @@ <dimen name="qs_media_album_radius">14dp</dimen> <dimen name="qs_media_info_margin">12dp</dimen> <dimen name="qs_media_info_spacing">8dp</dimen> - <dimen name="qs_media_icon_size">20dp</dimen> <dimen name="qs_media_icon_offset">4dp</dimen> <dimen name="qs_center_guideline_padding">10dp</dimen> <dimen name="qs_media_action_spacing">4dp</dimen> @@ -967,6 +970,7 @@ <dimen name="qs_seamless_icon_size">12dp</dimen> <dimen name="qs_media_disabled_seekbar_height">1dp</dimen> <dimen name="qs_media_enabled_seekbar_height">2dp</dimen> + <dimen name="qs_media_app_icon_size">24dp</dimen> <dimen name="qs_media_session_enabled_seekbar_vertical_padding">15dp</dimen> <dimen name="qs_media_session_disabled_seekbar_vertical_padding">16dp</dimen> @@ -979,12 +983,9 @@ <dimen name="qs_media_session_collapsed_guideline">144dp</dimen> <!-- Size of Smartspace media recommendations cards in the QSPanel carousel --> - <dimen name="qs_aa_media_rec_album_size_collapsed">72dp</dimen> - <dimen name="qs_aa_media_rec_album_size_expanded">76dp</dimen> - <dimen name="qs_aa_media_gradient_bg_width">32dp</dimen> - <dimen name="qs_aa_media_rec_album_margin">8dp</dimen> - <dimen name="qs_aa_media_rec_album_margin_vert">4dp</dimen> - <dimen name="qq_aa_media_rec_header_text_size">16sp</dimen> + <dimen name="qs_media_rec_album_size">88dp</dimen> + <dimen name="qs_media_rec_album_side_margin">16dp</dimen> + <dimen name="qs_media_rec_album_bottom_margin">8dp</dimen> <!-- Media tap-to-transfer chip for sender device --> <dimen name="media_ttt_chip_outer_padding">16dp</dimen> @@ -1367,7 +1368,7 @@ <dimen name="keyguard_unfold_translation_x">16dp</dimen> - <dimen name="fgs_manager_min_width_minor">100%</dimen> + <dimen name="fgs_manager_list_top_spacing">12dp</dimen> <!-- Dream overlay related dimensions --> <dimen name="dream_overlay_status_bar_height">60dp</dimen> @@ -1379,8 +1380,8 @@ <dimen name="dream_overlay_notification_indicator_size">6dp</dimen> <!-- Dream overlay complications related dimensions --> - <dimen name="dream_overlay_complication_clock_time_text_size">72sp</dimen> - <dimen name="dream_overlay_complication_clock_subtitle_text_size">18sp</dimen> + <dimen name="dream_overlay_complication_clock_time_text_size">100sp</dimen> + <dimen name="dream_overlay_complication_clock_subtitle_text_size">24sp</dimen> <dimen name="dream_overlay_complication_preview_text_size">36sp</dimen> <dimen name="dream_overlay_complication_preview_icon_padding">28dp</dimen> <dimen name="dream_overlay_complication_shadow_padding">2dp</dimen> diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml index ff71b4f5e405..5eacc3e6006b 100644 --- a/packages/SystemUI/res/values/ids.xml +++ b/packages/SystemUI/res/values/ids.xml @@ -170,5 +170,11 @@ <item type="id" name="action_move_bottom_right"/> <item type="id" name="action_move_to_edge_and_hide"/> <item type="id" name="action_move_out_edge_and_show"/> + + <!-- rounded corner view id --> + <item type="id" name="rounded_corner_top_left"/> + <item type="id" name="rounded_corner_top_right"/> + <item type="id" name="rounded_corner_bottom_left"/> + <item type="id" name="rounded_corner_bottom_right"/> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index b248efe93e98..f7acda7ec379 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1373,6 +1373,9 @@ <!-- Notification: Control panel: Label that displays when the app's notifications cannot be blocked. --> <string name="notification_unblockable_desc">These notifications can\'t be modified.</string> + <!-- Notification: Control panel: Label that displays when a notification cannot be blocked because it's attached to a phone/voip call. --> + <string name="notification_unblockable_call_desc">Call notifications can\'t be modified.</string> + <!-- Notification: Control panel: label that displays when viewing settings for a group of notifications posted to multiple channels. --> <string name="notification_multichannel_desc">This group of notifications cannot be configured here</string> @@ -2437,14 +2440,16 @@ <!-- Label for the entry point to open the dialog which shows currently running applications [CHAR LIMIT=NONE]--> <plurals name="fgs_manager_footer_label"> - <item quantity="one"><xliff:g id="count" example="1">%s</xliff:g> active app</item> - <item quantity="other"><xliff:g id="count" example="2">%s</xliff:g> active apps</item> + <item quantity="one"><xliff:g id="count" example="1">%s</xliff:g> app is active</item> + <item quantity="other"><xliff:g id="count" example="2">%s</xliff:g> apps are active</item> </plurals> <!-- Content description for a dot indicator in the running application indicating that there is new information [CHAR LIMIT=NONE] --> <string name="fgs_dot_content_description">New information</string> <!-- Title for dialog listing applications currently running [CHAR LIMIT=NONE]--> <string name="fgs_manager_dialog_title">Active apps</string> + <!-- Detailed message for dialog listing applications currently running [CHAR LIMIT=NONE]--> + <string name="fgs_manager_dialog_message">Even if you\u2019re not using these apps, they\u2019re still active and might affect battery life</string> <!-- Label of the button to stop an app from running [CHAR LIMIT=12]--> <string name="fgs_manager_app_item_stop_button_label">Stop</string> <!-- Label of the button to stop an app from running but the app is already stopped and the button is disabled [CHAR LIMIT=12]--> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index f97bbee3b152..c93c0652a070 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -653,16 +653,38 @@ <item name="android:textColor">?android:attr/textColorPrimary</item> </style> - <style name="MediaPlayer.AppIcon"> - <item name="android:background">@drawable/qs_media_icon_background</item> - <item name="android:backgroundTint">@color/media_player_solid_button_bg</item> - <item name="android:padding">4dp</item> + <style name="MediaPlayer.Recommendation"/> + + <style name="MediaPlayer.Recommendation.AlbumContainer"> + <item name="android:layout_width">@dimen/qs_media_rec_album_size</item> + <item name="android:layout_height">@dimen/qs_media_rec_album_size</item> + <item name="android:background">@drawable/qs_media_light_source</item> + <item name="android:layout_marginTop">@dimen/qs_media_padding</item> + <item name="android:layout_marginBottom">@dimen/qs_media_rec_album_bottom_margin</item> </style> - <style name="MediaPlayer.Album"> + <style name="MediaPlayer.Recommendation.Album"> <item name="android:backgroundTint">@color/media_player_album_bg</item> </style> + <style name="MediaPlayer.Recommendation.Text"> + <item name="android:layout_width">@dimen/qs_media_rec_album_size</item> + <item name="android:layout_height">wrap_content</item> + <item name="android:maxLines">1</item> + <item name="android:ellipsize">end</item> + <item name="android:textSize">14sp</item> + <item name="android:gravity">start</item> + </style> + + <style name="MediaPlayer.Recommendation.Text.Title"> + <item name="android:textColor">?android:attr/textColorPrimary</item> + </style> + + <style name="MediaPlayer.Recommendation.Text.Subtitle"> + <item name="android:textColor">?android:attr/textColorSecondary</item> + </style> + + <!-- Used to style charging animation AVD animation --> <style name="ChargingAnim" /> @@ -1083,6 +1105,11 @@ <item name="android:textDirection">locale</item> </style> + <style name="FgsManagerAppLabel" parent="TextAppearance.Dialog.Body"> + <item name="android:textDirection">locale</item> + <item name="android:textStyle">bold</item> + </style> + <style name="FgsManagerAppDuration"> <item name="android:fontFamily">?android:attr/textAppearanceSmall</item> <item name="android:textDirection">locale</item> diff --git a/packages/SystemUI/res/xml/media_recommendation_collapsed.xml b/packages/SystemUI/res/xml/media_recommendation_collapsed.xml index b6258d1c71eb..a6113473b065 100644 --- a/packages/SystemUI/res/xml/media_recommendation_collapsed.xml +++ b/packages/SystemUI/res/xml/media_recommendation_collapsed.xml @@ -16,91 +16,84 @@ --> <ConstraintSet xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto"> + xmlns:app="http://schemas.android.com/apk/res-auto" > <Constraint + android:id="@+id/sizing_view" + android:layout_width="match_parent" + android:layout_height="@dimen/qs_media_session_height_collapsed" + /> + + <!-- Only the constraintBottom and marginBottom are different. The rest of the constraints are + the same as the constraints in media_smartspace_recommendations. But due to how + ConstraintSets work, all the constraints need to be in the same place. + Ditto for the other cover containers. --> + <Constraint android:id="@+id/media_cover1_container" - android:layout_width="0dp" - android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed" - app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_collapsed" - app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" - android:layout_marginTop="@dimen/qs_media_padding" android:layout_marginBottom="@dimen/qs_media_padding" - android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin" - app:layout_constraintStart_toEndOf="@id/media_vertical_start_guideline" + style="@style/MediaPlayer.Recommendation.AlbumContainer" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@id/media_cover2_container" + android:layout_marginEnd="@dimen/qs_media_rec_album_side_margin" app:layout_constraintHorizontal_chainStyle="packed" - app:layout_constraintHorizontal_bias="1" - android:visibility="gone" /> + app:layout_constraintHorizontal_bias="1.0" + app:layout_constraintVertical_bias="0.5" + /> + + <Constraint + android:id="@+id/media_title1" + android:visibility="gone" + /> + + <Constraint + android:id="@+id/media_subtitle1" + android:visibility="gone" + /> <Constraint android:id="@+id/media_cover2_container" - android:layout_width="0dp" - android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed" - app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_collapsed" - android:layout_marginTop="@dimen/qs_media_padding" + app:layout_constraintBottom_toBottomOf="parent" android:layout_marginBottom="@dimen/qs_media_padding" - android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin" + style="@style/MediaPlayer.Recommendation.AlbumContainer" app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toEndOf="@id/media_cover1_container" app:layout_constraintEnd_toStartOf="@id/media_cover3_container" - app:layout_constraintHorizontal_chainStyle="packed" - app:layout_constraintHorizontal_bias="1" - android:visibility="gone" /> + android:layout_marginEnd="@dimen/qs_media_rec_album_side_margin" + app:layout_constraintVertical_bias="0.5" + /> + + <Constraint + android:id="@+id/media_title2" + android:visibility="gone" + /> + + <Constraint + android:id="@+id/media_subtitle2" + android:visibility="gone" + /> <Constraint android:id="@+id/media_cover3_container" - android:layout_width="0dp" - android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed" - app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_collapsed" - android:layout_marginTop="@dimen/qs_media_padding" + app:layout_constraintBottom_toBottomOf="parent" android:layout_marginBottom="@dimen/qs_media_padding" + style="@style/MediaPlayer.Recommendation.AlbumContainer" app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toEndOf="@id/media_cover2_container" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHorizontal_chainStyle="packed" - app:layout_constraintHorizontal_bias="1" - android:visibility="gone" /> + android:layout_marginEnd="@dimen/qs_media_padding" + app:layout_constraintVertical_bias="0.5" + /> <Constraint - android:id="@+id/media_cover4_container" - android:layout_width="0dp" - android:layout_height="0dp" - android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin" - app:layout_constraintTop_toBottomOf="@+id/media_cover1_container" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintStart_toEndOf="@id/media_vertical_start_guideline" - app:layout_constraintEnd_toStartOf="@id/media_cover5_container" - app:layout_constraintHorizontal_chainStyle="packed" - app:layout_constraintHorizontal_bias="1" - android:visibility="gone" /> + android:id="@+id/media_title3" + android:visibility="gone" + /> <Constraint - android:id="@+id/media_cover5_container" - android:layout_width="0dp" - android:layout_height="0dp" - android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin" - app:layout_constraintTop_toBottomOf="@+id/media_cover2_container" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintStart_toEndOf="@+id/media_cover4_container" - app:layout_constraintEnd_toStartOf="@+id/media_cover6_container" - app:layout_constraintHorizontal_chainStyle="packed" - app:layout_constraintHorizontal_bias="1" - android:visibility="gone" /> - - <Constraint - android:id="@+id/media_cover6_container" - android:layout_width="0dp" - android:layout_height="0dp" - app:layout_constraintTop_toBottomOf="@id/media_cover3_container" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintStart_toEndOf="@id/media_cover5_container" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHorizontal_chainStyle="packed" - app:layout_constraintHorizontal_bias="1" - android:visibility="gone" /> + android:id="@+id/media_subtitle3" + android:visibility="gone" + /> </ConstraintSet> diff --git a/packages/SystemUI/res/xml/media_recommendation_expanded.xml b/packages/SystemUI/res/xml/media_recommendation_expanded.xml index 2fb33415e0df..09ffebb8b4a9 100644 --- a/packages/SystemUI/res/xml/media_recommendation_expanded.xml +++ b/packages/SystemUI/res/xml/media_recommendation_expanded.xml @@ -15,113 +15,12 @@ ~ limitations under the License --> <ConstraintSet - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto"> + xmlns:android="http://schemas.android.com/apk/res/android" > <Constraint - android:id="@+id/media_cover1_container" - android:layout_width="0dp" - android:layout_height="@dimen/qs_aa_media_rec_album_size_expanded" - app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_expanded" - android:layout_marginTop="@dimen/qs_media_padding" - android:layout_marginBottom="@dimen/qs_aa_media_rec_album_margin_vert" - android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toTopOf="@+id/media_horizontal_center_guideline" - app:layout_constraintStart_toEndOf="@id/media_vertical_start_guideline" - app:layout_constraintEnd_toStartOf="@id/media_cover2_container" - app:layout_constraintHorizontal_chainStyle="packed" - app:layout_constraintHorizontal_bias="1" - app:layout_constraintVertical_chainStyle="packed" - app:layout_constraintVertical_bias="0" - android:visibility="gone" /> - - <Constraint - android:id="@+id/media_cover2_container" - android:layout_width="0dp" - android:layout_height="@dimen/qs_aa_media_rec_album_size_expanded" - app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_expanded" - android:layout_marginTop="@dimen/qs_media_padding" - android:layout_marginBottom="@dimen/qs_aa_media_rec_album_margin_vert" - android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toTopOf="@+id/media_horizontal_center_guideline" - app:layout_constraintStart_toEndOf="@id/media_cover1_container" - app:layout_constraintEnd_toStartOf="@id/media_cover3_container" - app:layout_constraintHorizontal_chainStyle="packed" - app:layout_constraintHorizontal_bias="1" - app:layout_constraintVertical_chainStyle="packed" - app:layout_constraintVertical_bias="0" - android:visibility="gone" /> - - <Constraint - android:id="@+id/media_cover3_container" - android:layout_width="0dp" - android:layout_height="@dimen/qs_aa_media_rec_album_size_expanded" - app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_expanded" - android:layout_marginTop="@dimen/qs_media_padding" - android:layout_marginBottom="@dimen/qs_aa_media_rec_album_margin_vert" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toTopOf="@+id/media_horizontal_center_guideline" - app:layout_constraintStart_toEndOf="@id/media_cover2_container" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHorizontal_chainStyle="packed" - app:layout_constraintHorizontal_bias="1" - app:layout_constraintVertical_chainStyle="packed" - app:layout_constraintVertical_bias="0" - android:visibility="gone" /> - - <Constraint - android:id="@+id/media_cover4_container" - android:layout_width="0dp" - android:layout_height="@dimen/qs_aa_media_rec_album_size_expanded" - app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_expanded" - android:layout_marginTop="@dimen/qs_aa_media_rec_album_margin_vert" - android:layout_marginBottom="@dimen/qs_media_padding" - android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin" - app:layout_constraintTop_toBottomOf="@+id/media_horizontal_center_guideline" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintStart_toEndOf="@id/media_vertical_start_guideline" - app:layout_constraintEnd_toStartOf="@id/media_cover5_container" - app:layout_constraintHorizontal_chainStyle="packed" - app:layout_constraintHorizontal_bias="1" - app:layout_constraintVertical_chainStyle="packed" - app:layout_constraintVertical_bias="1" - android:visibility="gone" /> - - <Constraint - android:id="@+id/media_cover5_container" - android:layout_width="0dp" - android:layout_height="@dimen/qs_aa_media_rec_album_size_expanded" - app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_expanded" - android:layout_marginTop="@dimen/qs_aa_media_rec_album_margin_vert" - android:layout_marginBottom="@dimen/qs_media_padding" - android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin" - app:layout_constraintTop_toBottomOf="@+id/media_horizontal_center_guideline" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintStart_toEndOf="@+id/media_cover4_container" - app:layout_constraintEnd_toStartOf="@+id/media_cover6_container" - app:layout_constraintHorizontal_chainStyle="packed" - app:layout_constraintHorizontal_bias="1" - app:layout_constraintVertical_chainStyle="packed" - app:layout_constraintVertical_bias="1" - android:visibility="gone" /> - - <Constraint - android:id="@+id/media_cover6_container" - android:layout_width="0dp" - android:layout_height="@dimen/qs_aa_media_rec_album_size_expanded" - app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_expanded" - android:layout_marginTop="@dimen/qs_aa_media_rec_album_margin_vert" - android:layout_marginBottom="@dimen/qs_media_padding" - app:layout_constraintTop_toBottomOf="@id/media_horizontal_center_guideline" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintStart_toEndOf="@id/media_cover5_container" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHorizontal_chainStyle="packed" - app:layout_constraintHorizontal_bias="1" - app:layout_constraintVertical_chainStyle="packed" - app:layout_constraintVertical_bias="1" - android:visibility="gone" /> + android:id="@+id/sizing_view" + android:layout_width="match_parent" + android:layout_height="@dimen/qs_media_session_height_expanded" + /> </ConstraintSet> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java index 238690cd48e2..938b1cae845e 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java @@ -80,21 +80,29 @@ public class PipSurfaceTransactionHelper { public PictureInPictureSurfaceTransaction scaleAndCrop( SurfaceControl.Transaction tx, SurfaceControl leash, - Rect sourceBounds, Rect destinationBounds, Rect insets) { + Rect sourceRectHint, Rect sourceBounds, Rect destinationBounds, Rect insets) { mTmpSourceRectF.set(sourceBounds); mTmpDestinationRect.set(sourceBounds); mTmpDestinationRect.inset(insets); // Scale by the shortest edge and offset such that the top/left of the scaled inset // source rect aligns with the top/left of the destination bounds - final float scale = sourceBounds.width() <= sourceBounds.height() - ? (float) destinationBounds.width() / sourceBounds.width() - : (float) destinationBounds.height() / sourceBounds.height(); + final float scale; + if (sourceRectHint.isEmpty() || sourceRectHint.width() == sourceBounds.width()) { + scale = sourceBounds.width() <= sourceBounds.height() + ? (float) destinationBounds.width() / sourceBounds.width() + : (float) destinationBounds.height() / sourceBounds.height(); + } else { + // scale by sourceRectHint if it's not edge-to-edge + scale = sourceRectHint.width() <= sourceRectHint.height() + ? (float) destinationBounds.width() / sourceRectHint.width() + : (float) destinationBounds.height() / sourceRectHint.height(); + } final float left = destinationBounds.left - (insets.left + sourceBounds.left) * scale; final float top = destinationBounds.top - (insets.top + sourceBounds.top) * scale; mTmpTransform.setScale(scale, scale); final float cornerRadius = getScaledCornerRadius(mTmpDestinationRect, destinationBounds); tx.setMatrix(leash, mTmpTransform, mTmpFloat9) - .setWindowCrop(leash, mTmpDestinationRect) + .setCrop(leash, mTmpDestinationRect) .setPosition(leash, left, top) .setCornerRadius(leash, cornerRadius) .setShadowRadius(leash, mShadowRadius); @@ -127,7 +135,7 @@ public class PipSurfaceTransactionHelper { adjustedPositionY = positionY - insets.left * scale; } tx.setMatrix(leash, mTmpTransform, mTmpFloat9) - .setWindowCrop(leash, mTmpDestinationRect) + .setCrop(leash, mTmpDestinationRect) .setPosition(leash, adjustedPositionX, adjustedPositionY) .setCornerRadius(leash, cornerRadius) .setShadowRadius(leash, mShadowRadius); diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java index bb7a0a719a74..01f417f147d7 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java @@ -568,7 +568,7 @@ public class RotationButtonController { } } - private class TaskStackListenerImpl extends TaskStackChangeListener { + private class TaskStackListenerImpl implements TaskStackChangeListener { // Invalidate any rotation suggestion on task change or activity orientation change // Note: all callbacks happen on main thread diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java index c5d54391959a..f65d82a5d6d2 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java @@ -26,30 +26,30 @@ import com.android.systemui.shared.recents.model.ThumbnailData; * An interface to track task stack changes. Classes should implement this instead of * {@link android.app.ITaskStackListener} to reduce IPC calls from system services. */ -public abstract class TaskStackChangeListener { +public interface TaskStackChangeListener { // Binder thread callbacks - public void onTaskStackChangedBackground() { } + default void onTaskStackChangedBackground() { } // Main thread callbacks - public void onTaskStackChanged() { } - public void onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) { } - public void onActivityPinned(String packageName, int userId, int taskId, int stackId) { } - public void onActivityUnpinned() { } - public void onActivityRestartAttempt(RunningTaskInfo task, boolean homeTaskVisible, + default void onTaskStackChanged() { } + default void onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) { } + default void onActivityPinned(String packageName, int userId, int taskId, int stackId) { } + default void onActivityUnpinned() { } + default void onActivityRestartAttempt(RunningTaskInfo task, boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) { } - public void onActivityForcedResizable(String packageName, int taskId, int reason) { } - public void onActivityDismissingDockedStack() { } - public void onActivityLaunchOnSecondaryDisplayFailed() { } + default void onActivityForcedResizable(String packageName, int taskId, int reason) { } + default void onActivityDismissingDockedStack() { } + default void onActivityLaunchOnSecondaryDisplayFailed() { } - public void onActivityLaunchOnSecondaryDisplayFailed(RunningTaskInfo taskInfo) { + default void onActivityLaunchOnSecondaryDisplayFailed(RunningTaskInfo taskInfo) { onActivityLaunchOnSecondaryDisplayFailed(); } /** * @see #onActivityLaunchOnSecondaryDisplayRerouted(RunningTaskInfo taskInfo) */ - public void onActivityLaunchOnSecondaryDisplayRerouted() { } + default void onActivityLaunchOnSecondaryDisplayRerouted() { } /** * Called when an activity was requested to be launched on a secondary display but was rerouted @@ -57,16 +57,16 @@ public abstract class TaskStackChangeListener { * * @param taskInfo info about the Activity's task */ - public void onActivityLaunchOnSecondaryDisplayRerouted(RunningTaskInfo taskInfo) { + default void onActivityLaunchOnSecondaryDisplayRerouted(RunningTaskInfo taskInfo) { onActivityLaunchOnSecondaryDisplayRerouted(); } - public void onTaskProfileLocked(int taskId, int userId) { } - public void onTaskCreated(int taskId, ComponentName componentName) { } - public void onTaskRemoved(int taskId) { } - public void onTaskMovedToFront(int taskId) { } + default void onTaskProfileLocked(int taskId, int userId) { } + default void onTaskCreated(int taskId, ComponentName componentName) { } + default void onTaskRemoved(int taskId) { } + default void onTaskMovedToFront(int taskId) { } - public void onTaskMovedToFront(RunningTaskInfo taskInfo) { + default void onTaskMovedToFront(RunningTaskInfo taskInfo) { onTaskMovedToFront(taskInfo.taskId); } @@ -74,13 +74,14 @@ public abstract class TaskStackChangeListener { * Called when a task’s description is changed due to an activity calling * ActivityManagerService.setTaskDescription * - * @param taskInfo info about the task which changed, with {@link TaskInfo#taskDescription} + * @param taskInfo info about the task which changed, with + * {@link RunningTaskInfo#taskDescription} */ - public void onTaskDescriptionChanged(RunningTaskInfo taskInfo) { } + default void onTaskDescriptionChanged(RunningTaskInfo taskInfo) { } - public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation) { } + default void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation) { } - public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) { } + default void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) { } /** * Called when a task is reparented to a stack on a different display. @@ -88,22 +89,22 @@ public abstract class TaskStackChangeListener { * @param taskId id of the task which was moved to a different display. * @param newDisplayId id of the new display. */ - public void onTaskDisplayChanged(int taskId, int newDisplayId) { } + default void onTaskDisplayChanged(int taskId, int newDisplayId) { } /** * Called when any additions or deletions to the recent tasks list have been made. */ - public void onRecentTaskListUpdated() { } + default void onRecentTaskListUpdated() { } /** @see ITaskStackListener#onRecentTaskListFrozenChanged(boolean) */ - public void onRecentTaskListFrozenChanged(boolean frozen) { } + default void onRecentTaskListFrozenChanged(boolean frozen) { } /** @see ITaskStackListener#onActivityRotation(int)*/ - public void onActivityRotation(int displayId) { } + default void onActivityRotation(int displayId) { } /** * Called when the lock task mode changes. See ActivityManager#LOCK_TASK_MODE_* and * LockTaskController. */ - public void onLockTaskModeChanged(int mode) { } + default void onLockTaskModeChanged(int mode) { } } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java index 32299f5643db..5bd81a42a814 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java @@ -86,6 +86,7 @@ public class WindowManagerWrapper { public static final int ITYPE_RIGHT_TAPPABLE_ELEMENT = InsetsState.ITYPE_RIGHT_TAPPABLE_ELEMENT; public static final int ITYPE_BOTTOM_TAPPABLE_ELEMENT = InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT; + public static final int ITYPE_SIZE = InsetsState.SIZE; public static final int ANIMATION_DURATION_RESIZE = InsetsController.ANIMATION_DURATION_RESIZE; public static final Interpolator RESIZE_INTERPOLATOR = InsetsController.RESIZE_INTERPOLATOR; diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ILauncherUnlockAnimationController.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ILauncherUnlockAnimationController.aidl index 366193c2cc41..b2295b94127b 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ILauncherUnlockAnimationController.aidl +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/ILauncherUnlockAnimationController.aidl @@ -30,7 +30,7 @@ interface ILauncherUnlockAnimationController { // Play a full unlock animation from 0f to 1f. This is used when System UI is unlocking from a // single action, such as biometric auth, and doesn't need to control individual frames. - oneway void playUnlockAnimation(boolean unlocked, long duration); + oneway void playUnlockAnimation(boolean unlocked, long duration, long startDelay); // Set the selected page on Launcher's smartspace. oneway void setSmartspaceSelectedPage(int selectedPage); diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt index ed973d6a6854..83b72e84a169 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt @@ -57,6 +57,15 @@ constructor( private val foldStateListener = FoldStateListener(context) private val timeoutRunnable = TimeoutRunnable() + /** + * Time after which [FOLD_UPDATE_FINISH_HALF_OPEN] is emitted following a + * [FOLD_UPDATE_START_CLOSING] or [FOLD_UPDATE_START_OPENING] event, if an end state is not + * reached. + */ + private val halfOpenedTimeoutMillis: Int = + context.resources.getInteger( + com.android.internal.R.integer.config_unfoldTransitionHalfFoldedTimeout) + private var isFolded = false private var isUnfoldHandled = true @@ -171,7 +180,7 @@ constructor( if (isTransitionInProgess) { cancelTimeout() } - handler.postDelayed(timeoutRunnable, HALF_OPENED_TIMEOUT_MILLIS) + handler.postDelayed(timeoutRunnable, halfOpenedTimeoutMillis.toLong()) } private fun cancelTimeout() { @@ -222,12 +231,6 @@ private fun stateToString(@FoldUpdate update: Int): String { private const val TAG = "DeviceFoldProvider" private const val DEBUG = false -/** - * Time after which [FOLD_UPDATE_FINISH_HALF_OPEN] is emitted following a - * [FOLD_UPDATE_START_CLOSING] or [FOLD_UPDATE_START_OPENING] event, if an end state is not reached. - */ -@VisibleForTesting const val HALF_OPENED_TIMEOUT_MILLIS = 600L - /** Threshold after which we consider the device fully unfolded. */ @VisibleForTesting const val FULLY_OPEN_THRESHOLD_DEGREES = 15f diff --git a/packages/SystemUI/src/com/android/keyguard/BouncerPanelExpansionCalculator.kt b/packages/SystemUI/src/com/android/keyguard/BouncerPanelExpansionCalculator.kt index 1b2ea3b257ab..a08c9000355f 100644 --- a/packages/SystemUI/src/com/android/keyguard/BouncerPanelExpansionCalculator.kt +++ b/packages/SystemUI/src/com/android/keyguard/BouncerPanelExpansionCalculator.kt @@ -23,7 +23,7 @@ object BouncerPanelExpansionCalculator { * Scale the alpha/position of the host view. */ @JvmStatic - fun getHostViewScaledExpansion(fraction: Float): Float { + fun showBouncerProgress(fraction: Float): Float { return when { fraction >= 0.9f -> 1f fraction < 0.6 -> 0f @@ -35,7 +35,7 @@ object BouncerPanelExpansionCalculator { * Scale the alpha/tint of the back scrim. */ @JvmStatic - fun getBackScrimScaledExpansion(fraction: Float): Float { + fun aboutToShowBouncerProgress(fraction: Float): Float { return MathUtils.constrain((fraction - 0.9f) / 0.1f, 0f, 1f) } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java index b3cf92741222..04c9a45af065 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java @@ -130,6 +130,24 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS } }; + private final KeyguardUnlockAnimationController.KeyguardUnlockAnimationListener + mKeyguardUnlockAnimationListener = + new KeyguardUnlockAnimationController.KeyguardUnlockAnimationListener() { + @Override + public void onSmartspaceSharedElementTransitionStarted() { + // The smartspace needs to be able to translate out of bounds in order to + // end up where the launcher's smartspace is, while its container is being + // swiped off the top of the screen. + setClipChildrenForUnlock(false); + } + + @Override + public void onUnlockAnimationFinished() { + // For performance reasons, reset this once the unlock animation ends. + setClipChildrenForUnlock(true); + } + }; + @Inject public KeyguardClockSwitchController( KeyguardClockSwitch keyguardClockSwitch, @@ -162,22 +180,6 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS mUiExecutor = uiExecutor; mKeyguardUnlockAnimationController = keyguardUnlockAnimationController; mDumpManager = dumpManager; - mKeyguardUnlockAnimationController.addKeyguardUnlockAnimationListener( - new KeyguardUnlockAnimationController.KeyguardUnlockAnimationListener() { - @Override - public void onSmartspaceSharedElementTransitionStarted() { - // The smartspace needs to be able to translate out of bounds in order to - // end up where the launcher's smartspace is, while its container is being - // swiped off the top of the screen. - setClipChildrenForUnlock(false); - } - - @Override - public void onUnlockAnimationFinished() { - // For performance reasons, reset this once the unlock animation ends. - setClipChildrenForUnlock(true); - } - }); } /** @@ -272,6 +274,9 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS ); updateDoubleLineClock(); + + mKeyguardUnlockAnimationController.addKeyguardUnlockAnimationListener( + mKeyguardUnlockAnimationListener); } int getNotificationIconAreaHeight() { @@ -287,6 +292,9 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS mView.setClockPlugin(null, mStatusBarStateController.getState()); mSecureSettings.unregisterContentObserver(mDoubleLineClockObserver); + + mKeyguardUnlockAnimationController.removeKeyguardUnlockAnimationListener( + mKeyguardUnlockAnimationListener); } /** diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java index 8c3e066849b9..239b478949d2 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java @@ -327,7 +327,7 @@ public class KeyguardHostViewController extends ViewController<KeyguardHostView> * @param fraction amount of the screen that should show. */ public void setExpansion(float fraction) { - float scaledFraction = BouncerPanelExpansionCalculator.getHostViewScaledExpansion(fraction); + float scaledFraction = BouncerPanelExpansionCalculator.showBouncerProgress(fraction); mView.setAlpha(MathUtils.constrain(1 - scaledFraction, 0f, 1f)); mView.setTranslationY(scaledFraction * mTranslationY); } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt index 5953611b454a..db2b4ac2c669 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt @@ -63,7 +63,8 @@ data class KeyguardFaceListenModel( val primaryUser: Boolean, val scanningAllowedByStrongAuth: Boolean, val secureCameraLaunched: Boolean, - val switchingUser: Boolean + val switchingUser: Boolean, + val udfpsBouncerShowing: Boolean ) : KeyguardListenModel() /** * Verbose debug information associated with [KeyguardUpdateMonitor.shouldTriggerActiveUnlock]. @@ -73,6 +74,7 @@ data class KeyguardActiveUnlockModel( override val userId: Int, override val listening: Boolean, // keep sorted + val awakeKeyguard: Boolean, val authInterruptActive: Boolean, val encryptedOrTimedOut: Boolean, val fpLockout: Boolean, diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index 3103219d8978..c0ba51f27fe2 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -555,7 +555,9 @@ public class KeyguardSecurityContainer extends FrameLayout { int bottomInset = insets.getInsetsIgnoringVisibility(systemBars()).bottom; int imeInset = insets.getInsets(ime()).bottom; int inset = max(bottomInset, imeInset); - setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), inset); + int paddingBottom = max(inset, getContext().getResources() + .getDimensionPixelSize(R.dimen.keyguard_security_view_bottom_margin)); + setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), paddingBottom); return insets.inset(0, 0, 0, inset); } @@ -700,6 +702,7 @@ public class KeyguardSecurityContainer extends FrameLayout { } public void reset() { + mViewMode.reset(); mDisappearAnimRunning = false; } @@ -798,9 +801,6 @@ public class KeyguardSecurityContainer extends FrameLayout { mUserSwitcherViewGroup = mView.findViewById(R.id.keyguard_bouncer_user_switcher); } - Drawable userIcon = findUserIcon(KeyguardUpdateMonitor.getCurrentUser()); - ((ImageView) mView.findViewById(R.id.user_icon)).setImageDrawable(userIcon); - updateSecurityViewLocation(); mUserSwitcher = mView.findViewById(R.id.user_switcher_header); @@ -813,6 +813,7 @@ public class KeyguardSecurityContainer extends FrameLayout { mPopup.dismiss(); mPopup = null; } + setupUserSwitcher(); } private Drawable findUserIcon(int userId) { @@ -858,6 +859,12 @@ public class KeyguardSecurityContainer extends FrameLayout { private void setupUserSwitcher() { final UserRecord currentUser = mUserSwitcherController.getCurrentUserRecord(); + if (currentUser == null) { + Log.wtf(TAG, "Current user in user switcher is null."); + return; + } + Drawable userIcon = findUserIcon(currentUser.info.id); + ((ImageView) mView.findViewById(R.id.user_icon)).setImageDrawable(userIcon); mUserSwitcher.setText(mUserSwitcherController.getCurrentUserName()); ViewGroup anchor = mView.findViewById(R.id.user_switcher_anchor); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java index 1a325d3586f4..ce4aad882df9 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java @@ -219,6 +219,11 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard mKeyguardSecurityCallback.userActivity(); showMessage(null, null); } + if (mUpdateMonitor.isFaceEnrolled() + && mUpdateMonitor.mRequestActiveUnlockOnUnlockIntent) { + mUpdateMonitor.requestActiveUnlock("unlock-intent, reason=swipeUpOnBouncer", + true); + } } }; private ConfigurationController.ConfigurationListener mConfigurationListener = diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index f1bec819560d..a6feedb50a12 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -56,6 +56,7 @@ import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.database.ContentObserver; import android.hardware.SensorPrivacyManager; +import android.hardware.biometrics.BiometricFaceConstants; import android.hardware.biometrics.BiometricFingerprintConstants; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricSourceType; @@ -88,6 +89,7 @@ import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; +import android.text.TextUtils; import android.util.Log; import android.util.SparseArray; import android.util.SparseBooleanArray; @@ -246,6 +248,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } } + public final boolean mRequestActiveUnlockOnAssistant; + public final boolean mRequestActiveUnlockOnWakeup; + public final boolean mInitiateActiveUnlockOnWakeup; + public final boolean mRequestActiveUnlockOnUnlockIntent; + public final boolean mRequestActiveUnlockOnBioFail; + private final Context mContext; private final boolean mIsPrimaryUser; private final boolean mIsAutomotive; @@ -281,6 +289,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private boolean mGoingToSleep; private boolean mBouncerFullyShown; private boolean mBouncerIsOrWillBeShowing; + private boolean mUdfpsBouncerShowing; private boolean mAuthInterruptActive; private boolean mNeedsSlowUnlockTransition; private boolean mAssistantVisible; @@ -451,10 +460,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } } - if (KeyguardUpdateMonitor.getCurrentUser() == userId && getUserHasTrust(userId)) { + if (KeyguardUpdateMonitor.getCurrentUser() == userId) { CharSequence message = null; - if (trustGrantedMessages != null && trustGrantedMessages.size() > 0) { - message = trustGrantedMessages.get(0); // for now only shows the first in the list + final boolean userHasTrust = getUserHasTrust(userId); + if (userHasTrust && trustGrantedMessages != null) { + for (String msg : trustGrantedMessages) { + if (!TextUtils.isEmpty(msg)) { + message = msg; + break; + } + } } for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); @@ -463,6 +478,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } } } + } @Override @@ -1354,8 +1370,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab void setAssistantVisible(boolean assistantVisible) { mAssistantVisible = assistantVisible; updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE); - if (mAssistantVisible) { - requestActiveUnlock(); + if (mAssistantVisible && mRequestActiveUnlockOnAssistant) { + requestActiveUnlock("assistant", false); } } @@ -1502,11 +1518,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @Override public void onAuthenticationFailed() { + if (mRequestActiveUnlockOnBioFail) { + requestActiveUnlock("biometric-failure, extra=fingerprintFailure", + true); + } handleFingerprintAuthFailed(); - - // TODO(b/225231929): Refactor as needed, add tests, etc. - mTrustManager.reportUserRequestedUnlock( - KeyguardUpdateMonitor.getCurrentUser(), true); } @Override @@ -1564,6 +1580,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @Override public void onAuthenticationFailed() { + if (shouldRequestActiveUnlockOnFaceError()) { + String reason = + mKeyguardBypassController.canBypass() ? "bypass" + : mUdfpsBouncerShowing ? "udfpsBouncer" : + mBouncerFullyShown ? "bouncer" : "udfpsFpDown"; + requestActiveUnlock("biometric-failure" + + ", extra=faceFailure-" + reason, true); + } + handleFaceAuthFailed(); if (mKeyguardBypassController != null) { mKeyguardBypassController.setUserHasDeviceEntryIntent(false); @@ -1592,12 +1617,23 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab if (mKeyguardBypassController != null) { mKeyguardBypassController.setUserHasDeviceEntryIntent(false); } + if (errMsgId == BiometricFaceConstants.FACE_ERROR_TIMEOUT + && shouldRequestActiveUnlockOnFaceError()) { + requestActiveUnlock("biometric-failure" + + ", extra=faceError-" + errMsgId, true); + } } @Override public void onAuthenticationAcquired(int acquireInfo) { handleFaceAcquired(acquireInfo); } + + private boolean shouldRequestActiveUnlockOnFaceError() { + return mRequestActiveUnlockOnBioFail + && (mKeyguardBypassController.canBypass() || mBouncerFullyShown + || mUdfpsBouncerShowing || mAuthController.isUdfpsFingerDown()); + } }; @VisibleForTesting @@ -1713,7 +1749,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab Trace.beginSection("KeyguardUpdateMonitor#handleStartedWakingUp"); Assert.isMainThread(); updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE); - requestActiveUnlock(); + if (mRequestActiveUnlockOnWakeup) { + requestActiveUnlock("wake-unlock"); + } else if (mInitiateActiveUnlockOnWakeup) { + initiateActiveUnlock("wake-initiate"); + } for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -1860,6 +1900,18 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab dumpManager.registerDumpable(getClass().getName(), this); mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class); + // TODO, b/222459888: add official configurable names to Settings.java + mRequestActiveUnlockOnWakeup = Settings.Global.getInt( + mContext.getContentResolver(), "wake-unlock", 0) == 1; + mInitiateActiveUnlockOnWakeup = Settings.Global.getInt( + mContext.getContentResolver(), "wake-initiate", 1) == 1; + mRequestActiveUnlockOnUnlockIntent = Settings.Global.getInt( + mContext.getContentResolver(), "unlock-intent", 0) == 1; + mRequestActiveUnlockOnBioFail = Settings.Global.getInt( + mContext.getContentResolver(), "bio-fail", 0) == 1; + mRequestActiveUnlockOnAssistant = Settings.Global.getInt( + mContext.getContentResolver(), "assistant", 0) == 1; + mHandler = new Handler(mainLooper) { @Override public void handleMessage(Message msg) { @@ -2194,7 +2246,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } // don't start running fingerprint until they're registered - if (!mAuthController.areAllAuthenticatorsRegistered()) { + if (!mAuthController.areAllFingerprintAuthenticatorsRegistered()) { return; } final boolean shouldListenForFingerprint = shouldListenForFingerprint(isUdfpsSupported()); @@ -2240,7 +2292,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } mAuthInterruptActive = active; updateFaceListeningState(BIOMETRIC_ACTION_UPDATE); - requestActiveUnlock(); + if (mRequestActiveUnlockOnWakeup) { + requestActiveUnlock("wake-unlock, extra=onReach"); + } else if (mInitiateActiveUnlockOnWakeup) { + initiateActiveUnlock("wake-initiate, extra=onReach"); + } } /** @@ -2290,25 +2346,69 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } /** - * Attempts to trigger active unlock. + * Initiates active unlock to get the unlock token ready. */ - public void requestActiveUnlock() { + public void initiateActiveUnlock(String reason) { // If this message exists, FP has already authenticated, so wait until that is handled if (mHandler.hasMessages(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE)) { return; } if (shouldTriggerActiveUnlock()) { - // TODO(b/225231929): Refactor surrounding code to reflect calling of new method + if (DEBUG) { + Log.d("ActiveUnlock", "initiate active unlock triggerReason=" + reason); + } mTrustManager.reportUserMayRequestUnlock(KeyguardUpdateMonitor.getCurrentUser()); } } + /** + * Attempts to trigger active unlock from trust agent. + */ + public void requestActiveUnlock(String reason, boolean dismissKeyguard) { + // If this message exists, FP has already authenticated, so wait until that is handled + if (mHandler.hasMessages(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE)) { + return; + } + + if (shouldTriggerActiveUnlock()) { + if (DEBUG) { + Log.d("ActiveUnlock", "reportUserRequestedUnlock triggerReason=" + reason + + " dismissKeyguard=" + dismissKeyguard); + } + mTrustManager.reportUserRequestedUnlock(KeyguardUpdateMonitor.getCurrentUser(), + dismissKeyguard); + } + } + + /** + * Attempts to trigger active unlock from trust agent. + * Only dismisses the keyguard if only face is enrolled (no FP) and bypass is enabled. + */ + public void requestActiveUnlock(String reason) { + requestActiveUnlock(reason, isFaceEnrolled() && !isUdfpsEnrolled() + && mKeyguardBypassController.getBypassEnabled()); + } + + /** + * Whether the UDFPS bouncer is showing. + */ + public void setUdfpsBouncerShowing(boolean showing) { + mUdfpsBouncerShowing = showing; + if (mUdfpsBouncerShowing) { + updateFaceListeningState(BIOMETRIC_ACTION_START); + if (mRequestActiveUnlockOnUnlockIntent) { + requestActiveUnlock("unlock-intent, extra=udfpsBouncer", true); + } + } + } + private boolean shouldTriggerActiveUnlock() { // Triggers: final boolean triggerActiveUnlockForAssistant = shouldTriggerActiveUnlockForAssistant(); - final boolean awakeKeyguard = mKeyguardIsVisible && mDeviceInteractive && !mGoingToSleep - && mStatusBarState != StatusBarState.SHADE_LOCKED; + final boolean awakeKeyguard = mBouncerFullyShown || mUdfpsBouncerShowing + || (mKeyguardIsVisible && mDeviceInteractive && !mGoingToSleep + && mStatusBarState != StatusBarState.SHADE_LOCKED); // Gates: final int user = getCurrentUser(); @@ -2341,20 +2441,19 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab && !mSecureCameraLaunched; // Aggregate relevant fields for debug logging. - if (DEBUG_ACTIVE_UNLOCK || DEBUG_SPEW) { - maybeLogListenerModelData( - new KeyguardActiveUnlockModel( - System.currentTimeMillis(), - user, - shouldTriggerActiveUnlock, - mAuthInterruptActive, - isEncryptedOrTimedOut, - fpLockedout, - isLockDown, - mSwitchingUser, - triggerActiveUnlockForAssistant, - userCanDismissLockScreen)); - } + maybeLogListenerModelData( + new KeyguardActiveUnlockModel( + System.currentTimeMillis(), + user, + shouldTriggerActiveUnlock, + awakeKeyguard, + mAuthInterruptActive, + isEncryptedOrTimedOut, + fpLockedout, + isLockDown, + mSwitchingUser, + triggerActiveUnlockForAssistant, + userCanDismissLockScreen)); return shouldTriggerActiveUnlock; } @@ -2507,7 +2606,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab || mOccludingAppRequestingFace || awakeKeyguard || shouldListenForFaceAssistant - || mAuthController.isUdfpsFingerDown()) + || mAuthController.isUdfpsFingerDown() + || mUdfpsBouncerShowing) && !mSwitchingUser && !faceDisabledForUser && becauseCannotSkipBouncer && !mKeyguardGoingAway && biometricEnabledForUser && !mLockIconPressed && strongAuthAllowsScanning && mIsPrimaryUser @@ -2537,7 +2637,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mIsPrimaryUser, strongAuthAllowsScanning, mSecureCameraLaunched, - mSwitchingUser)); + mSwitchingUser, + mUdfpsBouncerShowing)); } return shouldListen; @@ -2550,8 +2651,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } if (DEBUG_ACTIVE_UNLOCK - && model instanceof KeyguardActiveUnlockModel - && model.getListening()) { + && model instanceof KeyguardActiveUnlockModel) { mListenModels.add(model); return; } @@ -3133,6 +3233,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } if (wasBouncerFullyShown != mBouncerFullyShown) { + if (mBouncerFullyShown && mRequestActiveUnlockOnUnlockIntent) { + requestActiveUnlock("unlock-intent, reason=bouncerFullyShown", true); + } for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -3619,8 +3722,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab final int strongAuthFlags = mStrongAuthTracker.getStrongAuthForUser(userId); BiometricAuthenticated fingerprint = mUserFingerprintAuthenticated.get(userId); pw.println(" Fingerprint state (user=" + userId + ")"); - pw.println(" areAllAuthenticatorsRegistered=" - + mAuthController.areAllAuthenticatorsRegistered()); + pw.println(" areAllFpAuthenticatorsRegistered=" + + mAuthController.areAllFingerprintAuthenticatorsRegistered()); pw.println(" allowed=" + (fingerprint != null && isUnlockingWithBiometricAllowed(fingerprint.mIsStrongBiometric))); @@ -3641,6 +3744,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab pw.println(" shouldListenForUdfps=" + shouldListenForFingerprint(true)); pw.println(" mBouncerIsOrWillBeShowing=" + mBouncerIsOrWillBeShowing); pw.println(" mStatusBarState=" + StatusBarState.toString(mStatusBarState)); + pw.println(" mUdfpsBouncerShowing=" + mUdfpsBouncerShowing); } } if (mFaceManager != null && mFaceManager.isHardwareDetected()) { @@ -3667,6 +3771,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } mListenModels.print(pw); + pw.println("Enabled active unlock triggers:"); + pw.println(" mRequestActiveUnlockOnWakeup=" + mRequestActiveUnlockOnWakeup); + pw.println(" mInitiateActiveUnlockOnWakeup=" + mInitiateActiveUnlockOnWakeup); + pw.println(" mRequestActiveUnlockOnUnlockIntent=" + mRequestActiveUnlockOnUnlockIntent); + pw.println(" mRequestActiveUnlockOnBiometricFail=" + mRequestActiveUnlockOnBioFail); + pw.println(" mRequestActiveUnlockOnAssistant=" + mRequestActiveUnlockOnAssistant); + if (mIsAutomotive) { pw.println(" Running on Automotive build"); } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java index 295d77d55b56..ca8728aecb4c 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java @@ -55,6 +55,11 @@ public interface KeyguardViewController { void reset(boolean hideBouncerWhenShowing); /** + * Stop showing any alternate auth methods. + */ + void resetAlternateAuth(boolean forceUpdateScrim); + + /** * Called when the device started going to sleep. */ default void onStartedGoingToSleep() {}; diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java index db3037187520..239730d18934 100644 --- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java @@ -114,7 +114,6 @@ public class LockIconViewController extends ViewController<LockIconView> impleme private boolean mIsBouncerShowing; private boolean mRunningFPS; private boolean mCanDismissLockScreen; - private boolean mQsExpanded; private int mStatusBarState; private boolean mIsKeyguardShowing; private boolean mUserUnlockedWithBiometric; @@ -245,14 +244,6 @@ public class LockIconViewController extends ViewController<LockIconView> impleme return mView.getLocationTop(); } - /** - * Set whether qs is expanded. When QS is expanded, don't show a DisabledUdfps affordance. - */ - public void setQsExpanded(boolean expanded) { - mQsExpanded = expanded; - updateVisibility(); - } - private void updateVisibility() { if (mCancelDelayedUpdateVisibilityRunnable != null) { mCancelDelayedUpdateVisibilityRunnable.run(); @@ -331,7 +322,6 @@ public class LockIconViewController extends ViewController<LockIconView> impleme private boolean isLockScreen() { return !mIsDozing && !mIsBouncerShowing - && !mQsExpanded && mStatusBarState == StatusBarState.KEYGUARD; } @@ -394,7 +384,6 @@ public class LockIconViewController extends ViewController<LockIconView> impleme pw.println(" mRunningFPS: " + mRunningFPS); pw.println(" mCanDismissLockScreen: " + mCanDismissLockScreen); pw.println(" mStatusBarState: " + StatusBarState.toString(mStatusBarState)); - pw.println(" mQsExpanded: " + mQsExpanded); pw.println(" mInterpolatedDarkAmount: " + mInterpolatedDarkAmount); if (mView != null) { diff --git a/packages/SystemUI/src/com/android/systemui/LatencyTester.java b/packages/SystemUI/src/com/android/systemui/LatencyTester.java index 7afd43d1cb06..9cdce6400e56 100644 --- a/packages/SystemUI/src/com/android/systemui/LatencyTester.java +++ b/packages/SystemUI/src/com/android/systemui/LatencyTester.java @@ -23,21 +23,31 @@ import android.content.IntentFilter; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricSourceType; import android.os.Build; +import android.provider.DeviceConfig; +import androidx.annotation.NonNull; + +import com.android.internal.util.LatencyTracker; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.statusbar.phone.BiometricUnlockController; +import com.android.systemui.util.DeviceConfigProxy; +import com.android.systemui.util.concurrency.DelayableExecutor; + +import java.io.PrintWriter; import javax.inject.Inject; /** - * Class that only runs on debuggable builds that listens to broadcasts that simulate actions in the + * Class that only runs on debuggable builds with the LatencyTracker setting enabled + * that listens to broadcasts that simulate actions in the * system that are used for testing the latency. */ @SysUISingleton public class LatencyTester extends CoreStartable { - + private static final boolean DEFAULT_ENABLED = Build.IS_ENG; private static final String ACTION_FINGERPRINT_WAKE = "com.android.systemui.latency.ACTION_FINGERPRINT_WAKE"; @@ -46,42 +56,78 @@ public class LatencyTester extends CoreStartable { "com.android.systemui.latency.ACTION_FACE_WAKE"; private final BiometricUnlockController mBiometricUnlockController; private final BroadcastDispatcher mBroadcastDispatcher; + private final DeviceConfigProxy mDeviceConfigProxy; + + private boolean mEnabled; @Inject - public LatencyTester(Context context, BiometricUnlockController biometricUnlockController, - BroadcastDispatcher broadcastDispatcher) { + public LatencyTester( + Context context, + BiometricUnlockController biometricUnlockController, + BroadcastDispatcher broadcastDispatcher, + DeviceConfigProxy deviceConfigProxy, + @Main DelayableExecutor mainExecutor + ) { super(context); - mBiometricUnlockController = biometricUnlockController; mBroadcastDispatcher = broadcastDispatcher; + mDeviceConfigProxy = deviceConfigProxy; + + updateEnabled(); + mDeviceConfigProxy.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_LATENCY_TRACKER, + mainExecutor, properties -> updateEnabled()); } @Override public void start() { - if (!Build.IS_DEBUGGABLE) { - return; - } - - IntentFilter filter = new IntentFilter(); - filter.addAction(ACTION_FINGERPRINT_WAKE); - filter.addAction(ACTION_FACE_WAKE); - mBroadcastDispatcher.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (ACTION_FINGERPRINT_WAKE.equals(action)) { - fakeWakeAndUnlock(BiometricSourceType.FINGERPRINT); - } else if (ACTION_FACE_WAKE.equals(action)) { - fakeWakeAndUnlock(BiometricSourceType.FACE); - } - } - }, filter); + registerForBroadcasts(mEnabled); } private void fakeWakeAndUnlock(BiometricSourceType type) { + if (!mEnabled) { + return; + } mBiometricUnlockController.onBiometricAcquired(type, BiometricConstants.BIOMETRIC_ACQUIRED_GOOD); mBiometricUnlockController.onBiometricAuthenticated( KeyguardUpdateMonitor.getCurrentUser(), type, true /* isStrongBiometric */); } + + private void registerForBroadcasts(boolean register) { + if (register) { + IntentFilter filter = new IntentFilter(); + filter.addAction(ACTION_FINGERPRINT_WAKE); + filter.addAction(ACTION_FACE_WAKE); + mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter); + } else { + mBroadcastDispatcher.unregisterReceiver(mBroadcastReceiver); + } + } + + private void updateEnabled() { + boolean wasEnabled = mEnabled; + mEnabled = Build.IS_DEBUGGABLE + && mDeviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_LATENCY_TRACKER, + LatencyTracker.SETTINGS_ENABLED_KEY, DEFAULT_ENABLED); + if (mEnabled != wasEnabled) { + registerForBroadcasts(mEnabled); + } + } + + @Override + public void dump(@NonNull PrintWriter pw, @NonNull String[] args) { + pw.println("mEnabled=" + mEnabled); + } + + private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (ACTION_FINGERPRINT_WAKE.equals(action)) { + fakeWakeAndUnlock(BiometricSourceType.FINGERPRINT); + } else if (ACTION_FACE_WAKE.equals(action)) { + fakeWakeAndUnlock(BiometricSourceType.FACE); + } + } + }; } diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java index ff5715c606b6..9aa5fae1044d 100644 --- a/packages/SystemUI/src/com/android/systemui/Prefs.java +++ b/packages/SystemUI/src/com/android/systemui/Prefs.java @@ -63,7 +63,6 @@ public final class Prefs { Key.QS_WORK_ADDED, Key.QS_NIGHTDISPLAY_ADDED, Key.QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT, - Key.SEEN_MULTI_USER, Key.SEEN_RINGER_GUIDANCE_COUNT, Key.QS_HAS_TURNED_OFF_MOBILE_DATA, Key.TOUCHED_RINGER_TOGGLE, @@ -106,7 +105,6 @@ public final class Prefs { * Settings panel. */ String QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT = "QsLongPressTooltipShownCount"; - String SEEN_MULTI_USER = "HasSeenMultiUser"; String SEEN_RINGER_GUIDANCE_COUNT = "RingerGuidanceCount"; String QS_TILE_SPECS_REVEALED = "QsTileSpecsRevealed"; String QS_HAS_TURNED_OFF_MOBILE_DATA = "QsHasTurnedOffMobileData"; diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index 43d91a24bd3f..9b091018de9f 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -77,6 +77,7 @@ import com.android.systemui.decor.DecorProviderFactory; import com.android.systemui.decor.DecorProviderKt; import com.android.systemui.decor.OverlayWindow; import com.android.systemui.decor.PrivacyDotDecorProviderFactory; +import com.android.systemui.decor.RoundedCornerDecorProviderFactory; import com.android.systemui.decor.RoundedCornerResDelegate; import com.android.systemui.qs.SettingObserver; import com.android.systemui.settings.UserTracker; @@ -137,6 +138,9 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab @VisibleForTesting protected RoundedCornerResDelegate mRoundedCornerResDelegate; @VisibleForTesting + protected DecorProviderFactory mRoundedCornerFactory; + private int mProviderRefreshToken = 0; + @VisibleForTesting protected OverlayWindow[] mOverlays = null; @VisibleForTesting @Nullable @@ -282,16 +286,58 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab return mDotFactory.getHasProviders(); } + @NonNull + private List<DecorProvider> getProviders(boolean hasHwLayer) { + List<DecorProvider> decorProviders = new ArrayList<>(mDotFactory.getProviders()); + if (!hasHwLayer) { + decorProviders.addAll(mRoundedCornerFactory.getProviders()); + } + return decorProviders; + } + + private void updateDisplayIdToProviderFactories() { + mDotFactory.onDisplayUniqueIdChanged(mDisplayUniqueId); + mRoundedCornerFactory.onDisplayUniqueIdChanged(mDisplayUniqueId); + } + + /** + * Check that newProviders is the same list with decorProviders inside mOverlay. + * @param newProviders expected comparing DecorProviders + * @return true if same provider list + */ + @VisibleForTesting + boolean hasSameProviders(@NonNull List<DecorProvider> newProviders) { + final ArrayList<Integer> overlayViewIds = new ArrayList<>(); + if (mOverlays != null) { + for (OverlayWindow overlay : mOverlays) { + if (overlay == null) { + continue; + } + overlayViewIds.addAll(overlay.getViewIds()); + } + } + if (overlayViewIds.size() != newProviders.size()) { + return false; + } + + for (DecorProvider provider: newProviders) { + if (!overlayViewIds.contains(provider.getViewId())) { + return false; + } + } + return true; + } + private void startOnScreenDecorationsThread() { mRotation = mContext.getDisplay().getRotation(); mDisplayUniqueId = mContext.getDisplay().getUniqueId(); mRoundedCornerResDelegate = new RoundedCornerResDelegate(mContext.getResources(), mDisplayUniqueId); + mRoundedCornerFactory = new RoundedCornerDecorProviderFactory(mRoundedCornerResDelegate); mWindowManager = mContext.getSystemService(WindowManager.class); mDisplayManager = mContext.getSystemService(DisplayManager.class); mHwcScreenDecorationSupport = mContext.getDisplay().getDisplayDecorationSupport(); - updateRoundedCornerDrawable(); - updateRoundedCornerRadii(); + updateHwLayerRoundedCornerDrawable(); setupDecorations(); setupCameraListener(); @@ -343,18 +389,27 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab final String newUniqueId = mContext.getDisplay().getUniqueId(); if (!Objects.equals(newUniqueId, mDisplayUniqueId)) { mDisplayUniqueId = newUniqueId; - mRoundedCornerResDelegate.reloadAll(newUniqueId); final DisplayDecorationSupport newScreenDecorationSupport = mContext.getDisplay().getDisplayDecorationSupport(); - // When the value of mSupportHwcScreenDecoration is changed, re-setup the whole - // screen decoration. - if (!eq(newScreenDecorationSupport, mHwcScreenDecorationSupport)) { + + updateDisplayIdToProviderFactories(); + + // When providers or the value of mSupportHwcScreenDecoration is changed, + // re-setup the whole screen decoration. + if (!hasSameProviders(getProviders(newScreenDecorationSupport != null)) + || !eq(newScreenDecorationSupport, mHwcScreenDecorationSupport)) { mHwcScreenDecorationSupport = newScreenDecorationSupport; removeAllOverlays(); setupDecorations(); return; } - updateRoundedCornerDrawable(); + + if (mScreenDecorHwcLayer != null) { + updateHwLayerRoundedCornerDrawable(); + updateHwLayerRoundedCornerSize(); + } + + updateOverlayProviderViews(); } if (mCutoutViews != null) { final int size = mCutoutViews.length; @@ -369,7 +424,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab if (mScreenDecorHwcLayer != null) { mScreenDecorHwcLayer.onDisplayChanged(displayId); } - updateOrientation(); } }; @@ -396,6 +450,19 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab return null; } + private void removeRedundantOverlayViews(@NonNull List<DecorProvider> decorProviders) { + if (mOverlays == null) { + return; + } + int[] viewIds = decorProviders.stream().mapToInt(DecorProvider::getViewId).toArray(); + for (final OverlayWindow overlay : mOverlays) { + if (overlay == null) { + continue; + } + overlay.removeRedundantViews(viewIds); + } + } + private void removeOverlayView(@IdRes int id) { if (mOverlays == null) { return; @@ -411,9 +478,10 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab } private void setupDecorations() { - List<DecorProvider> decorProviders = mDotFactory.getProviders(); + if (hasRoundedCorners() || shouldDrawCutout() || isPrivacyDotEnabled()) { + List<DecorProvider> decorProviders = getProviders(mHwcScreenDecorationSupport != null); + removeRedundantOverlayViews(decorProviders); - if (hasRoundedCorners() || shouldDrawCutout() || !decorProviders.isEmpty()) { if (mHwcScreenDecorationSupport != null) { createHwcOverlay(); } else { @@ -427,7 +495,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab Pair<List<DecorProvider>, List<DecorProvider>> pair = DecorProviderKt.partitionAlignedBound(decorProviders, i); decorProviders = pair.getSecond(); - createOverlay(i, cutout, pair.getFirst(), isOnlyPrivacyDotInSwLayer); + createOverlay(i, pair.getFirst(), isOnlyPrivacyDotInSwLayer); } else { removeOverlay(i); } @@ -560,7 +628,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab private void createOverlay( @BoundsPosition int pos, - @Nullable DisplayCutout cutout, @NonNull List<DecorProvider> decorProviders, boolean isOnlyPrivacyDotInSwLayer) { if (mOverlays == null) { @@ -568,14 +635,12 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab } if (mOverlays[pos] != null) { - // When mOverlay[pos] is not null and only privacy dot in sw layer, use privacy dot - // view's visibility - mOverlays[pos].getRootView().setVisibility( - getWindowVisibility(mOverlays[pos], isOnlyPrivacyDotInSwLayer)); + initOverlay(mOverlays[pos], decorProviders, isOnlyPrivacyDotInSwLayer); return; } - mOverlays[pos] = overlayForPosition(pos, decorProviders, isOnlyPrivacyDotInSwLayer); + mOverlays[pos] = new OverlayWindow(mContext); + initOverlay(mOverlays[pos], decorProviders, isOnlyPrivacyDotInSwLayer); final ViewGroup overlayView = mOverlays[pos].getRootView(); overlayView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE); overlayView.setAlpha(0); @@ -590,7 +655,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab mCutoutViews[pos] = new DisplayCutoutView(mContext, pos); mCutoutViews[pos].setColor(mTintColor); overlayView.addView(mCutoutViews[pos]); - updateView(pos, cutout); + mCutoutViews[pos].updateRotation(mRotation); } mWindowManager.addView(overlayView, getWindowLayoutParams(pos)); @@ -641,42 +706,24 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab } /** - * Allow overrides for top/bottom positions + * Init OverlayWindow with decorProviders */ - private OverlayWindow overlayForPosition( - @BoundsPosition int pos, + private void initOverlay( + @NonNull OverlayWindow overlay, @NonNull List<DecorProvider> decorProviders, boolean isOnlyPrivacyDotInSwLayer) { - final OverlayWindow currentOverlay = new OverlayWindow(LayoutInflater.from(mContext), pos); - decorProviders.forEach(provider -> { - removeOverlayView(provider.getViewId()); - currentOverlay.addDecorProvider(provider, mRotation); - }); - // When only privacy dot in mOverlay, set the initial visibility of mOverlays to - // INVISIBLE and set it to VISIBLE when the privacy dot is showing. - if (isOnlyPrivacyDotInSwLayer) { - currentOverlay.getRootView().setVisibility(View.INVISIBLE); - } - return currentOverlay; - } - - private void updateView(@BoundsPosition int pos, @Nullable DisplayCutout cutout) { - if (mOverlays == null || mOverlays[pos] == null || mHwcScreenDecorationSupport != null) { - return; - } - - // update rounded corner view rotation - updateRoundedCornerView(pos, R.id.left, cutout); - updateRoundedCornerView(pos, R.id.right, cutout); - updateRoundedCornerSize( - mRoundedCornerResDelegate.getTopRoundedSize(), - mRoundedCornerResDelegate.getBottomRoundedSize()); - updateRoundedCornerImageView(); - - // update cutout view rotation - if (mCutoutViews != null && mCutoutViews[pos] != null) { - mCutoutViews[pos].updateRotation(mRotation); + if (!overlay.hasSameProviders(decorProviders)) { + decorProviders.forEach(provider -> { + if (overlay.getView(provider.getViewId()) != null) { + return; + } + removeOverlayView(provider.getViewId()); + overlay.addDecorProvider(provider, mRotation); + }); } + // Use visibility of privacy dot views if only privacy dot in sw layer + overlay.getRootView().setVisibility( + getWindowVisibility(overlay, isOnlyPrivacyDotInSwLayer)); } @VisibleForTesting @@ -849,7 +896,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab int oldRotation = mRotation; mPendingRotationChange = false; updateOrientation(); - updateRoundedCornerRadii(); if (DEBUG) Log.i(TAG, "onConfigChanged from rot " + oldRotation + " to " + mRotation); setupDecorations(); if (mOverlays != null) { @@ -910,109 +956,32 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab mDotViewController.setNewRotation(newRotation); } - if (mPendingRotationChange) { - return; - } - if (newRotation != mRotation) { + if (!mPendingRotationChange && newRotation != mRotation) { mRotation = newRotation; if (mScreenDecorHwcLayer != null) { mScreenDecorHwcLayer.pendingRotationChange = false; mScreenDecorHwcLayer.updateRotation(mRotation); + updateHwLayerRoundedCornerSize(); + updateHwLayerRoundedCornerDrawable(); } - if (mOverlays != null) { - updateLayoutParams(); - final DisplayCutout cutout = getCutout(); - for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) { - if (mOverlays[i] == null) { + updateLayoutParams(); + // update cutout view rotation + if (mCutoutViews != null) { + for (final DisplayCutoutView cutoutView: mCutoutViews) { + if (cutoutView == null) { continue; } - updateView(i, cutout); + cutoutView.updateRotation(mRotation); } } } - } - private void updateRoundedCornerRadii() { - // We should eventually move to just using the intrinsic size of the drawables since - // they should be sized to the exact pixels they want to cover. Therefore I'm purposely not - // upgrading all of the configs to contain (width, height) pairs. Instead assume that a - // device configured using the single integer config value is okay with drawing the corners - // as a square - final Size oldRoundedDefaultTop = mRoundedCornerResDelegate.getTopRoundedSize(); - final Size oldRoundedDefaultBottom = mRoundedCornerResDelegate.getBottomRoundedSize(); - mRoundedCornerResDelegate.reloadAll(mDisplayUniqueId); - final Size newRoundedDefaultTop = mRoundedCornerResDelegate.getTopRoundedSize(); - final Size newRoundedDefaultBottom = mRoundedCornerResDelegate.getBottomRoundedSize(); - - if (oldRoundedDefaultTop.getWidth() != newRoundedDefaultTop.getWidth() - || oldRoundedDefaultBottom.getWidth() != newRoundedDefaultBottom.getWidth()) { - onTuningChanged(SIZE, null); - } - } - - private void updateRoundedCornerView(@BoundsPosition int pos, int id, - @Nullable DisplayCutout cutout) { - final View rounded = mOverlays[pos].getRootView().findViewById(id); - if (rounded == null) { - return; - } - rounded.setVisibility(View.GONE); - if (shouldShowSwLayerRoundedCorner(pos, cutout)) { - final int gravity = getRoundedCornerGravity(pos, id == R.id.left); - ((FrameLayout.LayoutParams) rounded.getLayoutParams()).gravity = gravity; - setRoundedCornerOrientation(rounded, gravity); - rounded.setVisibility(View.VISIBLE); - } - } - - private int getRoundedCornerGravity(@BoundsPosition int pos, boolean isStart) { - final int rotatedPos = getBoundPositionFromRotation(pos, mRotation); - switch (rotatedPos) { - case BOUNDS_POSITION_LEFT: - return isStart ? Gravity.TOP | Gravity.LEFT : Gravity.BOTTOM | Gravity.LEFT; - case BOUNDS_POSITION_TOP: - return isStart ? Gravity.TOP | Gravity.LEFT : Gravity.TOP | Gravity.RIGHT; - case BOUNDS_POSITION_RIGHT: - return isStart ? Gravity.TOP | Gravity.RIGHT : Gravity.BOTTOM | Gravity.RIGHT; - case BOUNDS_POSITION_BOTTOM: - return isStart ? Gravity.BOTTOM | Gravity.LEFT : Gravity.BOTTOM | Gravity.RIGHT; - default: - throw new IllegalArgumentException("Incorrect position: " + rotatedPos); - } + // update all provider views inside overlay + updateOverlayProviderViews(); } - /** - * Configures the rounded corner drawable's view matrix based on the gravity. - * - * The gravity describes which corner to configure for, and the drawable we are rotating is - * assumed to be oriented for the top-left corner of the device regardless of the target corner. - * Therefore we need to rotate 180 degrees to get a bottom-left corner, and mirror in the x- or - * y-axis for the top-right and bottom-left corners. - */ - private void setRoundedCornerOrientation(View corner, int gravity) { - corner.setRotation(0); - corner.setScaleX(1); - corner.setScaleY(1); - switch (gravity) { - case Gravity.TOP | Gravity.LEFT: - return; - case Gravity.TOP | Gravity.RIGHT: - corner.setScaleX(-1); // flip X axis - return; - case Gravity.BOTTOM | Gravity.LEFT: - corner.setScaleY(-1); // flip Y axis - return; - case Gravity.BOTTOM | Gravity.RIGHT: - corner.setRotation(180); - return; - default: - throw new IllegalArgumentException("Unsupported gravity: " + gravity); - } - } private boolean hasRoundedCorners() { - return mRoundedCornerResDelegate.getBottomRoundedSize().getWidth() > 0 - || mRoundedCornerResDelegate.getTopRoundedSize().getWidth() > 0 - || mRoundedCornerResDelegate.isMultipleRadius(); + return mRoundedCornerFactory.getHasProviders(); } private boolean isDefaultShownOverlayPos(@BoundsPosition int pos, @@ -1066,6 +1035,19 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab context.getResources(), context.getDisplay().getUniqueId()); } + private void updateOverlayProviderViews() { + if (mOverlays == null) { + return; + } + ++mProviderRefreshToken; + for (final OverlayWindow overlay: mOverlays) { + if (overlay == null) { + continue; + } + overlay.onReloadResAndMeasure(null, mProviderRefreshToken, mRotation, mDisplayUniqueId); + } + } + private void updateLayoutParams() { if (mOverlays == null) { return; @@ -1085,63 +1067,33 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab return; } mExecutor.execute(() -> { - if (mOverlays == null) return; - if (SIZE.equals(key)) { - boolean hasReloadRoundedCornerRes = false; - if (newValue != null) { - try { - mRoundedCornerResDelegate.updateTuningSizeFactor( - Integer.parseInt(newValue)); - hasReloadRoundedCornerRes = true; - } catch (Exception e) { - } - } - - // When onTuningChanged() is not called through updateRoundedCornerRadii(), - // we need to reload rounded corner res to prevent incorrect dimen - if (!hasReloadRoundedCornerRes) { - mRoundedCornerResDelegate.reloadAll(mDisplayUniqueId); + if (mOverlays == null || !SIZE.equals(key)) { + return; + } + ++mProviderRefreshToken; + try { + final int sizeFactor = Integer.parseInt(newValue); + mRoundedCornerResDelegate.updateTuningSizeFactor(sizeFactor, mProviderRefreshToken); + } catch (NumberFormatException e) { + mRoundedCornerResDelegate.updateTuningSizeFactor(null, mProviderRefreshToken); + } + Integer[] filterIds = { + R.id.rounded_corner_top_left, + R.id.rounded_corner_top_right, + R.id.rounded_corner_bottom_left, + R.id.rounded_corner_bottom_right + }; + for (final OverlayWindow overlay: mOverlays) { + if (overlay == null) { + continue; } - - updateRoundedCornerSize( - mRoundedCornerResDelegate.getTopRoundedSize(), - mRoundedCornerResDelegate.getBottomRoundedSize()); + overlay.onReloadResAndMeasure(filterIds, mProviderRefreshToken, mRotation, + mDisplayUniqueId); } + updateHwLayerRoundedCornerSize(); }); } - private void updateRoundedCornerDrawable() { - mRoundedCornerResDelegate.reloadAll(mDisplayUniqueId); - updateRoundedCornerImageView(); - } - - private void updateRoundedCornerImageView() { - final Drawable top = mRoundedCornerResDelegate.getTopRoundedDrawable(); - final Drawable bottom = mRoundedCornerResDelegate.getBottomRoundedDrawable(); - - if (mScreenDecorHwcLayer != null) { - mScreenDecorHwcLayer.updateRoundedCornerDrawable(top, bottom); - return; - } - - if (mOverlays == null) { - return; - } - final ColorStateList colorStateList = ColorStateList.valueOf(mTintColor); - for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) { - if (mOverlays[i] == null) { - continue; - } - final ViewGroup overlayView = mOverlays[i].getRootView(); - ((ImageView) overlayView.findViewById(R.id.left)).setImageTintList(colorStateList); - ((ImageView) overlayView.findViewById(R.id.right)).setImageTintList(colorStateList); - ((ImageView) overlayView.findViewById(R.id.left)).setImageDrawable( - isTopRoundedCorner(i, R.id.left) ? top : bottom); - ((ImageView) overlayView.findViewById(R.id.right)).setImageDrawable( - isTopRoundedCorner(i, R.id.right) ? top : bottom); - } - } - private void updateHwLayerRoundedCornerDrawable() { if (mScreenDecorHwcLayer == null) { return; @@ -1156,25 +1108,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab mScreenDecorHwcLayer.updateRoundedCornerDrawable(topDrawable, bottomDrawable); } - @VisibleForTesting - boolean isTopRoundedCorner(@BoundsPosition int pos, int id) { - switch (pos) { - case BOUNDS_POSITION_LEFT: - case BOUNDS_POSITION_RIGHT: - if (mRotation == ROTATION_270) { - return id == R.id.left ? false : true; - } else { - return id == R.id.left ? true : false; - } - case BOUNDS_POSITION_TOP: - return true; - case BOUNDS_POSITION_BOTTOM: - return false; - default: - throw new IllegalArgumentException("Unknown bounds position"); - } - } - private void updateHwLayerRoundedCornerSize() { if (mScreenDecorHwcLayer == null) { return; @@ -1186,28 +1119,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab mScreenDecorHwcLayer.updateRoundedCornerSize(topWidth, bottomWidth); } - private void updateRoundedCornerSize(Size sizeTop, Size sizeBottom) { - - if (mScreenDecorHwcLayer != null) { - mScreenDecorHwcLayer.updateRoundedCornerSize(sizeTop.getWidth(), sizeBottom.getWidth()); - return; - } - - if (mOverlays == null) { - return; - } - for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) { - if (mOverlays[i] == null) { - continue; - } - final ViewGroup overlayView = mOverlays[i].getRootView(); - setSize(overlayView.findViewById(R.id.left), - isTopRoundedCorner(i, R.id.left) ? sizeTop : sizeBottom); - setSize(overlayView.findViewById(R.id.right), - isTopRoundedCorner(i, R.id.right) ? sizeTop : sizeBottom); - } - } - @VisibleForTesting protected void setSize(View view, Size pixelSize) { LayoutParams params = view.getLayoutParams(); diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/ModeSwitchesController.java b/packages/SystemUI/src/com/android/systemui/accessibility/ModeSwitchesController.java index 5e48ee3d2366..0cc1b2d92e00 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/ModeSwitchesController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/ModeSwitchesController.java @@ -28,6 +28,8 @@ import android.view.Display; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.dagger.SysUISingleton; +import javax.inject.Inject; + /** * A class to control {@link MagnificationModeSwitch}. It shows the button UI with following * conditions: @@ -44,6 +46,7 @@ public class ModeSwitchesController implements SwitchListener { private final DisplayIdIndexSupplier<MagnificationModeSwitch> mSwitchSupplier; private SwitchListener mSwitchListenerDelegate; + @Inject public ModeSwitchesController(Context context) { mSwitchSupplier = new SwitchSupplier(context, context.getSystemService(DisplayManager.class), this::onSwitch); diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java index 807ff21bf47a..a1428f3120c8 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java @@ -353,6 +353,8 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mSourceBounds.setEmpty(); updateSystemUIStateIfNeeded(); mContext.unregisterComponentCallbacks(this); + // Notify source bounds empty when magnification is deleted. + mWindowMagnifierCallback.onSourceBoundsChanged(mDisplayId, new Rect()); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AlternateUdfpsTouchProvider.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AlternateUdfpsTouchProvider.kt new file mode 100644 index 000000000000..f4f39a1df11b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AlternateUdfpsTouchProvider.kt @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.biometrics + +/** + * Interface for controlling the on finger down & on finger up events. + */ +interface AlternateUdfpsTouchProvider { + + /** + * This operation is used to notify the Fingerprint HAL that + * a fingerprint has been detected on the device's screen. + * + * See fingerprint/ISession#onPointerDown for more details. + */ + fun onPointerDown(pointerId: Long, x: Int, y: Int, minor: Float, major: Float) + + /** + * onPointerUp: + * + * This operation can be invoked when the HAL is performing any one of: ISession#authenticate, + * ISession#enroll, ISession#detectInteraction. This operation is used to indicate + * that a fingerprint that was previously down, is now up. + * + * See fingerprint/ISession#onPointerUp for more details. + */ + fun onPointerUp(pointerId: Long) +} diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java index b2673e923008..233f3648aeb3 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java @@ -56,7 +56,9 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.widget.LockPatternUtils; import com.android.systemui.R; import com.android.systemui.animation.Interpolators; +import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.util.concurrency.DelayableExecutor; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -110,6 +112,8 @@ public class AuthContainerView extends LinearLayout @ContainerState private int mContainerState = STATE_UNKNOWN; private final Set<Integer> mFailedModalities = new HashSet<Integer>(); + private final @Background DelayableExecutor mBackgroundExecutor; + // Non-null only if the dialog is in the act of dismissing and has not sent the reason yet. @Nullable @AuthDialogCallback.DismissedReason private Integer mPendingCallbackReason; // HAT received from LockSettingsService when credential is verified. @@ -192,7 +196,7 @@ public class AuthContainerView extends LinearLayout return this; } - public AuthContainerView build(int[] sensorIds, + public AuthContainerView build(@Background DelayableExecutor bgExecutor, int[] sensorIds, @Nullable List<FingerprintSensorPropertiesInternal> fpProps, @Nullable List<FaceSensorPropertiesInternal> faceProps, @NonNull WakefulnessLifecycle wakefulnessLifecycle, @@ -200,7 +204,7 @@ public class AuthContainerView extends LinearLayout @NonNull LockPatternUtils lockPatternUtils) { mConfig.mSensorIds = sensorIds; return new AuthContainerView(mConfig, fpProps, faceProps, wakefulnessLifecycle, - userManager, lockPatternUtils, new Handler(Looper.getMainLooper())); + userManager, lockPatternUtils, new Handler(Looper.getMainLooper()), bgExecutor); } } @@ -253,7 +257,8 @@ public class AuthContainerView extends LinearLayout @NonNull WakefulnessLifecycle wakefulnessLifecycle, @NonNull UserManager userManager, @NonNull LockPatternUtils lockPatternUtils, - @NonNull Handler mainHandler) { + @NonNull Handler mainHandler, + @NonNull @Background DelayableExecutor bgExecutor) { super(config.mContext); mConfig = config; @@ -277,6 +282,7 @@ public class AuthContainerView extends LinearLayout mBackgroundView = mFrameLayout.findViewById(R.id.background); mPanelView = mFrameLayout.findViewById(R.id.panel); mPanelController = new AuthPanelController(mContext, mPanelView); + mBackgroundExecutor = bgExecutor; // Inflate biometric view only if necessary. if (Utils.isBiometricAllowed(mConfig.mPromptInfo)) { @@ -384,6 +390,7 @@ public class AuthContainerView extends LinearLayout mCredentialView.setPromptInfo(mConfig.mPromptInfo); mCredentialView.setPanelController(mPanelController, animatePanel); mCredentialView.setShouldAnimateContents(animateContents); + mCredentialView.setBackgroundExecutor(mBackgroundExecutor); mFrameLayout.addView(mCredentialView); } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java index aaf18b309db2..15d0648ae163 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java @@ -37,6 +37,7 @@ import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricManager.Authenticators; import android.hardware.biometrics.BiometricManager.BiometricMultiSensorMode; import android.hardware.biometrics.BiometricPrompt; +import android.hardware.biometrics.BiometricStateListener; import android.hardware.biometrics.IBiometricContextListener; import android.hardware.biometrics.IBiometricSysuiReceiver; import android.hardware.biometrics.PromptInfo; @@ -45,7 +46,6 @@ import android.hardware.face.FaceManager; import android.hardware.face.FaceSensorPropertiesInternal; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; -import android.hardware.fingerprint.FingerprintStateListener; import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback; import android.hardware.fingerprint.IUdfpsHbmListener; import android.os.Bundle; @@ -64,11 +64,13 @@ import com.android.internal.widget.LockPatternUtils; import com.android.systemui.CoreStartable; import com.android.systemui.assist.ui.DisplayUtils; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.doze.DozeReceiver; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CommandQueue; +import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.concurrency.Execution; import java.util.ArrayList; @@ -136,9 +138,10 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba @NonNull private final SparseBooleanArray mUdfpsEnrolledForUser; @NonNull private final SensorPrivacyManager mSensorPrivacyManager; private final WakefulnessLifecycle mWakefulnessLifecycle; - private boolean mAllAuthenticatorsRegistered; + private boolean mAllFingerprintAuthenticatorsRegistered; @NonNull private final UserManager mUserManager; @NonNull private final LockPatternUtils mLockPatternUtils; + private final @Background DelayableExecutor mBackgroundExecutor; @VisibleForTesting final TaskStackListener mTaskStackListener = new TaskStackListener() { @@ -154,12 +157,12 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba @Override public void onAllAuthenticatorsRegistered( List<FingerprintSensorPropertiesInternal> sensors) { - mHandler.post(() -> handleAllAuthenticatorsRegistered(sensors)); + mHandler.post(() -> handleAllFingerprintAuthenticatorsRegistered(sensors)); } }; - private final FingerprintStateListener mFingerprintStateListener = - new FingerprintStateListener() { + private final BiometricStateListener mBiometricStateListener = + new BiometricStateListener() { @Override public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) { mHandler.post( @@ -231,20 +234,20 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba } /** - * Whether all authentictors have been registered. + * Whether all fingerprint authentictors have been registered. */ - public boolean areAllAuthenticatorsRegistered() { - return mAllAuthenticatorsRegistered; + public boolean areAllFingerprintAuthenticatorsRegistered() { + return mAllFingerprintAuthenticatorsRegistered; } - private void handleAllAuthenticatorsRegistered( + private void handleAllFingerprintAuthenticatorsRegistered( List<FingerprintSensorPropertiesInternal> sensors) { mExecution.assertIsMainThread(); if (DEBUG) { Log.d(TAG, "handleAllAuthenticatorsRegistered | sensors: " + Arrays.toString( sensors.toArray())); } - mAllAuthenticatorsRegistered = true; + mAllFingerprintAuthenticatorsRegistered = true; mFpProps = sensors; List<FingerprintSensorPropertiesInternal> udfpsProps = new ArrayList<>(); List<FingerprintSensorPropertiesInternal> sidefpsProps = new ArrayList<>(); @@ -278,7 +281,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba for (Callback cb : mCallbacks) { cb.onAllAuthenticatorsRegistered(); } - mFingerprintManager.registerFingerprintStateListener(mFingerprintStateListener); + mFingerprintManager.registerBiometricStateListener(mBiometricStateListener); } private void handleEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) { @@ -507,13 +510,15 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba @NonNull UserManager userManager, @NonNull LockPatternUtils lockPatternUtils, @NonNull StatusBarStateController statusBarStateController, - @Main Handler handler) { + @Main Handler handler, + @Background DelayableExecutor bgExecutor) { super(context); mExecution = execution; mWakefulnessLifecycle = wakefulnessLifecycle; mUserManager = userManager; mLockPatternUtils = lockPatternUtils; mHandler = handler; + mBackgroundExecutor = bgExecutor; mCommandQueue = commandQueue; mActivityTaskManager = activityTaskManager; mFingerprintManager = fingerprintManager; @@ -839,6 +844,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba // Create a new dialog but do not replace the current one yet. final AuthDialog newDialog = buildDialog( + mBackgroundExecutor, promptInfo, requireConfirmation, userId, @@ -934,9 +940,9 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba } } - protected AuthDialog buildDialog(PromptInfo promptInfo, boolean requireConfirmation, - int userId, int[] sensorIds, String opPackageName, - boolean skipIntro, long operationId, long requestId, + protected AuthDialog buildDialog(@Background DelayableExecutor bgExecutor, + PromptInfo promptInfo, boolean requireConfirmation, int userId, int[] sensorIds, + String opPackageName, boolean skipIntro, long operationId, long requestId, @BiometricMultiSensorMode int multiSensorConfig, @NonNull WakefulnessLifecycle wakefulnessLifecycle, @NonNull UserManager userManager, @@ -951,8 +957,8 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba .setOperationId(operationId) .setRequestId(requestId) .setMultiSensorConfig(multiSensorConfig) - .build(sensorIds, mFpProps, mFaceProps, wakefulnessLifecycle, userManager, - lockPatternUtils); + .build(bgExecutor, sensorIds, mFpProps, mFaceProps, wakefulnessLifecycle, + userManager, lockPatternUtils); } /** diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java index ed84a37682e4..4fa835e038ec 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java @@ -53,6 +53,8 @@ import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.VerifyCredentialResponse; import com.android.systemui.R; import com.android.systemui.animation.Interpolators; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.util.concurrency.DelayableExecutor; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -99,6 +101,8 @@ public abstract class AuthCredentialView extends LinearLayout { protected int mEffectiveUserId; protected ErrorTimer mErrorTimer; + protected @Background DelayableExecutor mBackgroundExecutor; + interface Callback { void onCredentialMatched(byte[] attestation); } @@ -217,6 +221,10 @@ public abstract class AuthCredentialView extends LinearLayout { mContainerView = containerView; } + void setBackgroundExecutor(@Background DelayableExecutor bgExecutor) { + mBackgroundExecutor = bgExecutor; + } + @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); @@ -377,27 +385,33 @@ public abstract class AuthCredentialView extends LinearLayout { } private void showLastAttemptBeforeWipeDialog() { - final AlertDialog alertDialog = new AlertDialog.Builder(mContext) - .setTitle(R.string.biometric_dialog_last_attempt_before_wipe_dialog_title) - .setMessage( - getLastAttemptBeforeWipeMessage(getUserTypeForWipe(), mCredentialType)) - .setPositiveButton(android.R.string.ok, null) - .create(); - alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL); - alertDialog.show(); + mBackgroundExecutor.execute(() -> { + final AlertDialog alertDialog = new AlertDialog.Builder(mContext) + .setTitle(R.string.biometric_dialog_last_attempt_before_wipe_dialog_title) + .setMessage( + getLastAttemptBeforeWipeMessage(getUserTypeForWipe(), mCredentialType)) + .setPositiveButton(android.R.string.ok, null) + .create(); + alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL); + mHandler.post(alertDialog::show); + }); } private void showNowWipingDialog() { - final AlertDialog alertDialog = new AlertDialog.Builder(mContext) - .setMessage(getNowWipingMessage(getUserTypeForWipe())) - .setPositiveButton( - com.android.settingslib.R.string.failed_attempts_now_wiping_dialog_dismiss, - null /* OnClickListener */) - .setOnDismissListener( - dialog -> mContainerView.animateAway(AuthDialogCallback.DISMISSED_ERROR)) - .create(); - alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL); - alertDialog.show(); + mBackgroundExecutor.execute(() -> { + String nowWipingMessage = getNowWipingMessage(getUserTypeForWipe()); + final AlertDialog alertDialog = new AlertDialog.Builder(mContext) + .setMessage(nowWipingMessage) + .setPositiveButton( + com.android.settingslib.R.string.failed_attempts_now_wiping_dialog_dismiss, + null /* OnClickListener */) + .setOnDismissListener( + dialog -> mContainerView.animateAway( + AuthDialogCallback.DISMISSED_ERROR)) + .create(); + alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL); + mHandler.post(alertDialog::show); + }); } private @UserType int getUserTypeForWipe() { @@ -412,6 +426,7 @@ public abstract class AuthCredentialView extends LinearLayout { } } + // This should not be called on the main thread to avoid making an IPC. private String getLastAttemptBeforeWipeMessage( @UserType int userType, @Utils.CredentialType int credentialType) { switch (userType) { @@ -442,6 +457,7 @@ public abstract class AuthCredentialView extends LinearLayout { } } + // This should not be called on the main thread to avoid making an IPC. private String getLastAttemptBeforeWipeProfileMessage( @Utils.CredentialType int credentialType) { return mDevicePolicyManager.getResources().getString( diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt index 33126b3887da..76c1dbcaf20c 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt @@ -145,6 +145,7 @@ class AuthRippleController @Inject constructor( val lightRevealScrim = centralSurfaces.lightRevealScrim if (statusBarStateController.isDozing || biometricUnlockController.isWakeAndUnlock) { circleReveal?.let { + lightRevealScrim?.revealAmount = 0f lightRevealScrim?.revealEffect = it startLightRevealScrimOnKeyguardFadingAway = true } @@ -168,7 +169,8 @@ class AuthRippleController @Inject constructor( startDelay = keyguardStateController.keyguardFadingAwayDelay addUpdateListener { animator -> if (lightRevealScrim.revealEffect != circleReveal) { - // if something else took over the reveal, let's do nothing. + // if something else took over the reveal, let's cancel ourselves + cancel() return@addUpdateListener } lightRevealScrim.revealAmount = animator.animatedValue as Float diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index 2ac240885faa..284724687abc 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -133,6 +133,7 @@ public class UdfpsController implements DozeReceiver { // sensors, this, in addition to a lot of the code here, will be updated. @VisibleForTesting final FingerprintSensorPropertiesInternal mSensorProps; @NonNull private final ActivityLaunchAnimator mActivityLaunchAnimator; + @Nullable private final AlternateUdfpsTouchProvider mAlternateTouchProvider; // Tracks the velocity of a touch to help filter out the touches that move too fast. @Nullable private VelocityTracker mVelocityTracker; @@ -384,6 +385,7 @@ public class UdfpsController implements DozeReceiver { mActivePointerId = event.getPointerId(0); mVelocityTracker.addMovement(event); handled = true; + mAcquiredReceived = false; } if ((withinSensorArea || fromUdfpsView) && shouldTryToDismissKeyguard()) { Log.v(TAG, "onTouch | dismiss keyguard ACTION_DOWN"); @@ -537,7 +539,8 @@ public class UdfpsController implements DozeReceiver { @NonNull UnlockedScreenOffAnimationController unlockedScreenOffAnimationController, @NonNull SystemUIDialogManager dialogManager, @NonNull LatencyTracker latencyTracker, - @NonNull ActivityLaunchAnimator activityLaunchAnimator) { + @NonNull ActivityLaunchAnimator activityLaunchAnimator, + @NonNull Optional<AlternateUdfpsTouchProvider> aternateTouchProvider) { mContext = context; mExecution = execution; mVibrator = vibrator; @@ -566,6 +569,7 @@ public class UdfpsController implements DozeReceiver { mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; mLatencyTracker = latencyTracker; mActivityLaunchAnimator = activityLaunchAnimator; + mAlternateTouchProvider = aternateTouchProvider.orElse(null); mSensorProps = findFirstUdfps(); // At least one UDFPS sensor exists @@ -782,6 +786,7 @@ public class UdfpsController implements DozeReceiver { private void onFingerDown(long requestId, int x, int y, float minor, float major) { mExecution.assertIsMainThread(); + if (mOverlay == null) { Log.w(TAG, "Null request in onFingerDown"); return; @@ -799,9 +804,18 @@ public class UdfpsController implements DozeReceiver { if (!mKeyguardUpdateMonitor.isFaceDetectionRunning()) { mKeyguardUpdateMonitor.requestFaceAuth(/* userInitiatedRequest */ false); } + + if (mKeyguardUpdateMonitor.mRequestActiveUnlockOnUnlockIntent) { + mKeyguardUpdateMonitor.requestActiveUnlock("unlock-intent extra=udfpsFingerDown", + true); + } } mOnFingerDown = true; - mFingerprintManager.onPointerDown(requestId, mSensorProps.sensorId, x, y, minor, major); + if (mAlternateTouchProvider != null) { + mAlternateTouchProvider.onPointerDown(requestId, x, y, minor, major); + } else { + mFingerprintManager.onPointerDown(requestId, mSensorProps.sensorId, x, y, minor, major); + } Trace.endAsyncSection("UdfpsController.e2e.onPointerDown", 0); final UdfpsView view = mOverlay.getOverlayView(); @@ -822,7 +836,11 @@ public class UdfpsController implements DozeReceiver { mActivePointerId = -1; mAcquiredReceived = false; if (mOnFingerDown) { - mFingerprintManager.onPointerUp(requestId, mSensorProps.sensorId); + if (mAlternateTouchProvider != null) { + mAlternateTouchProvider.onPointerUp(requestId); + } else { + mFingerprintManager.onPointerUp(requestId, mSensorProps.sensorId); + } for (Callback cb : mCallbacks) { cb.onFingerUp(); } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java index 7efdd1a8b949..67d0db22b3cf 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java @@ -43,6 +43,8 @@ import com.airbnb.lottie.LottieAnimationView; import com.airbnb.lottie.LottieProperty; import com.airbnb.lottie.model.KeyPath; +import java.io.PrintWriter; + /** * View corresponding with udfps_keyguard_view.xml */ @@ -124,13 +126,16 @@ public class UdfpsKeyguardView extends UdfpsAnimationView { - mMaxBurnInOffsetY, darkAmountForAnimation); mBurnInProgress = MathUtils.lerp(0f, getBurnInProgressOffset(), darkAmountForAnimation); - if (mAnimatingBetweenAodAndLockscreen) { + if (mAnimatingBetweenAodAndLockscreen && !mPauseAuth) { mBgProtection.setAlpha(1f - mInterpolatedDarkAmount); mLockScreenFp.setTranslationX(mBurnInOffsetX); mLockScreenFp.setTranslationY(mBurnInOffsetY); mLockScreenFp.setProgress(1f - mInterpolatedDarkAmount); mLockScreenFp.setAlpha(1f - mInterpolatedDarkAmount); + } else if (mInterpolatedDarkAmount == 0f) { + mBgProtection.setAlpha(mAlpha / 255f); + mLockScreenFp.setAlpha(mAlpha / 255f); } else { mBgProtection.setAlpha(0f); mLockScreenFp.setAlpha(0f); @@ -140,6 +145,11 @@ public class UdfpsKeyguardView extends UdfpsAnimationView { mAodFp.setTranslationY(mBurnInOffsetY); mAodFp.setProgress(mBurnInProgress); mAodFp.setAlpha(mInterpolatedDarkAmount); + + // done animating between AoD & LS + if (mInterpolatedDarkAmount == 1f || mInterpolatedDarkAmount == 0f) { + mAnimatingBetweenAodAndLockscreen = false; + } } void requestUdfps(boolean request, int color) { @@ -179,15 +189,7 @@ public class UdfpsKeyguardView extends UdfpsAnimationView { @Override protected int updateAlpha() { int alpha = super.updateAlpha(); - if (mFullyInflated) { - if (mInterpolatedDarkAmount == 0f) { - mLockScreenFp.setAlpha(alpha / 255f); - mBgProtection.setAlpha(alpha / 255f); - } else { - updateBurnInOffsets(); - } - } - + updateBurnInOffsets(); return alpha; } @@ -202,9 +204,7 @@ public class UdfpsKeyguardView extends UdfpsAnimationView { void onDozeAmountChanged(float linear, float eased, boolean animatingBetweenAodAndLockscreen) { mAnimatingBetweenAodAndLockscreen = animatingBetweenAodAndLockscreen; mInterpolatedDarkAmount = eased; - updateAlpha(); - updateBurnInOffsets(); } /** @@ -235,19 +235,30 @@ public class UdfpsKeyguardView extends UdfpsAnimationView { mBackgroundInAnimator.start(); } + /** + * Print debugging information for this class. + */ + public void dump(PrintWriter pw) { + pw.println("UdfpsKeyguardView (" + this + ")"); + pw.println(" mPauseAuth=" + mPauseAuth); + pw.println(" mUnpausedAlpha=" + getUnpausedAlpha()); + pw.println(" mUdfpsRequested=" + mUdfpsRequested); + pw.println(" mInterpolatedDarkAmount=" + mInterpolatedDarkAmount); + pw.println(" mAnimatingBetweenAodAndLockscreen=" + mAnimatingBetweenAodAndLockscreen); + } + private final AsyncLayoutInflater.OnInflateFinishedListener mLayoutInflaterFinishListener = new AsyncLayoutInflater.OnInflateFinishedListener() { @Override public void onInflateFinished(View view, int resid, ViewGroup parent) { mFullyInflated = true; - parent.addView(view); - mAodFp = findViewById(R.id.udfps_aod_fp); - mLockScreenFp = findViewById(R.id.udfps_lockscreen_fp); - mBgProtection = findViewById(R.id.udfps_keyguard_fp_bg); + mAodFp = view.findViewById(R.id.udfps_aod_fp); + mLockScreenFp = view.findViewById(R.id.udfps_lockscreen_fp); + mBgProtection = view.findViewById(R.id.udfps_keyguard_fp_bg); - updateBurnInOffsets(); updateColor(); updateAlpha(); + parent.addView(view); // requires call to invalidate to update the color mLockScreenFp.addValueCallback( diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java index 5d131f2a0046..e8cfd422cc8a 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java @@ -21,10 +21,10 @@ import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import android.animation.ValueAnimator; import android.annotation.NonNull; import android.content.res.Configuration; -import android.util.Log; import android.util.MathUtils; import android.view.MotionEvent; +import com.android.keyguard.BouncerPanelExpansionCalculator; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.R; import com.android.systemui.animation.ActivityLaunchAnimator; @@ -65,13 +65,13 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud private boolean mShowingUdfpsBouncer; private boolean mUdfpsRequested; - private boolean mQsExpanded; + private float mQsExpansion; private boolean mFaceDetectRunning; private int mStatusBarState; private float mTransitionToFullShadeProgress; private float mLastDozeAmount; private long mLastUdfpsBouncerShowTime = -1; - private float mStatusBarExpansion; + private float mPanelExpansionFraction; private boolean mLaunchTransitionFadingAway; private boolean mIsLaunchingActivity; private float mActivityLaunchProgress; @@ -82,7 +82,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud * {@link KeyguardBouncer#EXPANSION_HIDDEN} (1f) */ private float mInputBouncerHiddenAmount; - private boolean mIsBouncerVisible; + private boolean mIsGenericBouncerShowing; // whether UDFPS bouncer or input bouncer is visible protected UdfpsKeyguardViewController( @NonNull UdfpsKeyguardView view, @@ -149,9 +149,8 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud mLaunchTransitionFadingAway = mKeyguardStateController.isLaunchTransitionFadingAway(); mKeyguardStateController.addCallback(mKeyguardStateControllerCallback); mStatusBarState = getStatusBarStateController().getState(); - mQsExpanded = mKeyguardViewManager.isQsExpanded(); - mInputBouncerHiddenAmount = KeyguardBouncer.EXPANSION_HIDDEN; - mIsBouncerVisible = mKeyguardViewManager.bouncerIsOrWillBeShowing(); + mQsExpansion = mKeyguardViewManager.getQsExpansion(); + updateGenericBouncerVisibility(); mConfigurationController.addCallback(mConfigurationListener); getPanelExpansionStateManager().addExpansionListener(mPanelExpansionListener); updateAlpha(); @@ -185,15 +184,17 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud pw.println("mShowingUdfpsBouncer=" + mShowingUdfpsBouncer); pw.println("mFaceDetectRunning=" + mFaceDetectRunning); pw.println("mStatusBarState=" + StatusBarState.toString(mStatusBarState)); - pw.println("mQsExpanded=" + mQsExpanded); - pw.println("mIsBouncerVisible=" + mIsBouncerVisible); + pw.println("mTransitionToFullShadeProgress=" + mTransitionToFullShadeProgress); + pw.println("mQsExpansion=" + mQsExpansion); + pw.println("mIsGenericBouncerShowing=" + mIsGenericBouncerShowing); pw.println("mInputBouncerHiddenAmount=" + mInputBouncerHiddenAmount); - pw.println("mStatusBarExpansion=" + mStatusBarExpansion); + pw.println("mPanelExpansionFraction=" + mPanelExpansionFraction); pw.println("unpausedAlpha=" + mView.getUnpausedAlpha()); pw.println("mUdfpsRequested=" + mUdfpsRequested); - pw.println("mView.mUdfpsRequested=" + mView.mUdfpsRequested); pw.println("mLaunchTransitionFadingAway=" + mLaunchTransitionFadingAway); pw.println("mLastDozeAmount=" + mLastDozeAmount); + + mView.dump(pw); } /** @@ -224,6 +225,8 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud } else { mKeyguardUpdateMonitor.requestFaceAuthOnOccludingApp(false); } + + updateGenericBouncerVisibility(); updateAlpha(); updatePauseAuth(); return true; @@ -240,16 +243,12 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud } if (mUdfpsRequested && !getNotificationShadeVisible() - && (!mIsBouncerVisible + && (!mIsGenericBouncerShowing || mInputBouncerHiddenAmount != KeyguardBouncer.EXPANSION_VISIBLE) && mKeyguardStateController.isShowing()) { return false; } - if (mView.getDialogSuggestedAlpha() == 0f) { - return true; - } - if (mLaunchTransitionFadingAway) { return true; } @@ -262,17 +261,12 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud return true; } - if (mQsExpanded) { + if (mInputBouncerHiddenAmount < .5f) { return true; } - if (mInputBouncerHiddenAmount < .5f || mIsBouncerVisible) { - if (!getStatusBarStateController().isDozing()) { - return true; - } else { - Log.e(TAG, "Bouncer state claims visible on doze hiddenAmount=" - + mInputBouncerHiddenAmount + " bouncerVisible=" + mIsBouncerVisible); - } + if (mView.getUnpausedAlpha() < (255 * .1)) { + return true; } return false; @@ -312,6 +306,9 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud /** * Set the progress we're currently transitioning to the full shade. 0.0f means we're not * transitioning yet, while 1.0f means we've fully dragged down. + * + * For example, start swiping down to expand the notification shade from the empty space in + * the middle of the lock screen. */ public void setTransitionToFullShadeProgress(float progress) { mTransitionToFullShadeProgress = progress; @@ -324,15 +321,21 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud */ @Override public void updateAlpha() { - // fade icon on transitions to showing the status bar, but if mUdfpsRequested, then - // the keyguard is occluded by some application - so instead use the input bouncer - // hidden amount to determine the fade - float expansion = mUdfpsRequested ? mInputBouncerHiddenAmount : mStatusBarExpansion; + // Fade icon on transitions to showing the status bar or bouncer, but if mUdfpsRequested, + // then the keyguard is occluded by some application - so instead use the input bouncer + // hidden amount to determine the fade. + float expansion = mUdfpsRequested ? mInputBouncerHiddenAmount : mPanelExpansionFraction; + int alpha = mShowingUdfpsBouncer ? 255 : (int) MathUtils.constrain( MathUtils.map(.5f, .9f, 0f, 255f, expansion), 0f, 255f); + if (!mShowingUdfpsBouncer) { + // swipe from top of the lockscreen to expand full QS: + alpha *= (1.0f - Interpolators.EMPHASIZED_DECELERATE.getInterpolation(mQsExpansion)); + + // swipe from the middle (empty space) of lockscreen to expand the notification shade: alpha *= (1.0f - mTransitionToFullShadeProgress); // Fade out the icon if we are animating an activity launch over the lockscreen and the @@ -348,6 +351,21 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud mView.setUnpausedAlpha(alpha); } + /** + * Updates mIsGenericBouncerShowing (whether any bouncer is showing) and updates the + * mInputBouncerHiddenAmount to reflect whether the input bouncer is fully showing or not. + */ + private void updateGenericBouncerVisibility() { + mIsGenericBouncerShowing = mKeyguardViewManager.isBouncerShowing(); // includes altBouncer + final boolean altBouncerShowing = mKeyguardViewManager.isShowingAlternateAuth(); + if (altBouncerShowing || !mKeyguardViewManager.bouncerIsOrWillBeShowing()) { + mInputBouncerHiddenAmount = 1f; + } else if (mIsGenericBouncerShowing) { + // input bouncer is fully showing + mInputBouncerHiddenAmount = 0f; + } + } + private final StatusBarStateController.StateListener mStateListener = new StatusBarStateController.StateListener() { @Override @@ -410,9 +428,14 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud return false; } + /** + * Set the amount qs is expanded. Forxample, swipe down from the top of the + * lock screen to start the full QS expansion. + */ @Override - public void setQsExpanded(boolean expanded) { - mQsExpanded = expanded; + public void setQsExpansion(float qsExpansion) { + mQsExpansion = qsExpansion; + updateAlpha(); updatePauseAuth(); } @@ -431,14 +454,13 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud updatePauseAuth(); } + /** + * Only called on primary auth bouncer changes, not on whether the UDFPS bouncer + * visibility changes. + */ @Override public void onBouncerVisibilityChanged() { - mIsBouncerVisible = mKeyguardViewManager.isBouncerShowing(); - if (!mIsBouncerVisible) { - mInputBouncerHiddenAmount = 1f; - } else if (mKeyguardViewManager.isBouncerShowing()) { - mInputBouncerHiddenAmount = 0f; - } + updateGenericBouncerVisibility(); updateAlpha(); updatePauseAuth(); } @@ -471,7 +493,9 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud @Override public void onPanelExpansionChanged( float fraction, boolean expanded, boolean tracking) { - mStatusBarExpansion = fraction; + mPanelExpansionFraction = + mKeyguardViewManager.isBouncerInTransit() ? BouncerPanelExpansionCalculator + .aboutToShowBouncerProgress(fraction) : fraction; updateAlpha(); } }; diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/ActionReceiver.kt b/packages/SystemUI/src/com/android/systemui/broadcast/ActionReceiver.kt index 4315cb0e14d7..ca36375c2cde 100644 --- a/packages/SystemUI/src/com/android/systemui/broadcast/ActionReceiver.kt +++ b/packages/SystemUI/src/com/android/systemui/broadcast/ActionReceiver.kt @@ -39,6 +39,13 @@ import java.util.concurrent.atomic.AtomicInteger * * This class has no sync controls, so make sure to only make modifications from the background * thread. + * + * This class takes the following actions: + * * [registerAction]: action to register this receiver (with the proper filter) with [Context]. + * * [unregisterAction]: action to unregister this receiver with [Context]. + * * [testPendingRemovalAction]: action to check if a particular [BroadcastReceiver] registered + * with [BroadcastDispatcher] has been unregistered and is pending removal. See + * [PendingRemovalStore]. */ class ActionReceiver( private val action: String, @@ -46,7 +53,8 @@ class ActionReceiver( private val registerAction: BroadcastReceiver.(IntentFilter) -> Unit, private val unregisterAction: BroadcastReceiver.() -> Unit, private val bgExecutor: Executor, - private val logger: BroadcastDispatcherLogger + private val logger: BroadcastDispatcherLogger, + private val testPendingRemovalAction: (BroadcastReceiver, Int) -> Boolean ) : BroadcastReceiver(), Dumpable { companion object { @@ -106,7 +114,8 @@ class ActionReceiver( // Immediately return control to ActivityManager bgExecutor.execute { receiverDatas.forEach { - if (it.filter.matchCategories(intent.categories) == null) { + if (it.filter.matchCategories(intent.categories) == null && + !testPendingRemovalAction(it.receiver, userId)) { it.executor.execute { it.receiver.pendingResult = pendingResult it.receiver.onReceive(context, intent) diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt index 1c27e320dd83..d757b629c829 100644 --- a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt +++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt @@ -31,10 +31,13 @@ import android.util.SparseArray import com.android.internal.annotations.VisibleForTesting import com.android.systemui.Dumpable import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dump.DumpManager import com.android.systemui.settings.UserTracker import java.io.PrintWriter import java.util.concurrent.Executor +import javax.inject.Inject data class ReceiverData( val receiver: BroadcastReceiver, @@ -63,13 +66,15 @@ private const val DEBUG = true * Broadcast handling may be asynchronous *without* calling goAsync(), as it's running within sysui * and doesn't need to worry about being killed. */ -open class BroadcastDispatcher constructor ( +@SysUISingleton +open class BroadcastDispatcher @Inject constructor( private val context: Context, - private val bgLooper: Looper, - private val bgExecutor: Executor, + @Background private val bgLooper: Looper, + @Background private val bgExecutor: Executor, private val dumpManager: DumpManager, private val logger: BroadcastDispatcherLogger, - private val userTracker: UserTracker + private val userTracker: UserTracker, + private val removalPendingStore: PendingRemovalStore ) : Dumpable { // Only modify in BG thread @@ -167,6 +172,7 @@ open class BroadcastDispatcher constructor ( * @param receiver The receiver to unregister. It will be unregistered for all users. */ open fun unregisterReceiver(receiver: BroadcastReceiver) { + removalPendingStore.tagForRemoval(receiver, UserHandle.USER_ALL) handler.obtainMessage(MSG_REMOVE_RECEIVER, receiver).sendToTarget() } @@ -177,13 +183,21 @@ open class BroadcastDispatcher constructor ( * @param user The user associated to the registered [receiver]. It can be [UserHandle.ALL]. */ open fun unregisterReceiverForUser(receiver: BroadcastReceiver, user: UserHandle) { + removalPendingStore.tagForRemoval(receiver, user.identifier) handler.obtainMessage(MSG_REMOVE_RECEIVER_FOR_USER, user.identifier, 0, receiver) .sendToTarget() } @VisibleForTesting protected open fun createUBRForUser(userId: Int) = - UserBroadcastDispatcher(context, userId, bgLooper, bgExecutor, logger) + UserBroadcastDispatcher( + context, + userId, + bgLooper, + bgExecutor, + logger, + removalPendingStore + ) override fun dump(pw: PrintWriter, args: Array<out String>) { pw.println("Broadcast dispatcher:") @@ -193,6 +207,8 @@ open class BroadcastDispatcher constructor ( ipw.println("User ${receiversByUser.keyAt(index)}") receiversByUser.valueAt(index).dump(ipw, args) } + ipw.println("Pending removal:") + removalPendingStore.dump(ipw, args) ipw.decreaseIndent() } @@ -223,10 +239,20 @@ open class BroadcastDispatcher constructor ( for (it in 0 until receiversByUser.size()) { receiversByUser.valueAt(it).unregisterReceiver(msg.obj as BroadcastReceiver) } + removalPendingStore.clearPendingRemoval( + msg.obj as BroadcastReceiver, + UserHandle.USER_ALL + ) } MSG_REMOVE_RECEIVER_FOR_USER -> { - receiversByUser.get(msg.arg1)?.unregisterReceiver(msg.obj as BroadcastReceiver) + val userId = if (msg.arg1 == UserHandle.USER_CURRENT) { + userTracker.userId + } else { + msg.arg1 + } + receiversByUser.get(userId)?.unregisterReceiver(msg.obj as BroadcastReceiver) + removalPendingStore.clearPendingRemoval(msg.obj as BroadcastReceiver, userId) } else -> super.handleMessage(msg) } diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcherModule.java b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcherModule.java new file mode 100644 index 000000000000..cc08188ef618 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcherModule.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.broadcast; + +import com.android.systemui.CoreStartable; + +import dagger.Binds; +import dagger.Module; +import dagger.multibindings.ClassKey; +import dagger.multibindings.IntoMap; + +/** */ +@Module +public abstract class BroadcastDispatcherModule { + /** Ensures BroadcastDispatcher is initialized. */ + @Binds + @IntoMap + @ClassKey(BroadcastDispatcherStartable.class) + abstract CoreStartable bindsBroadastDispatcherStartable(BroadcastDispatcherStartable s); +} diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcherStartable.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcherStartable.kt new file mode 100644 index 000000000000..d7b263a323ca --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcherStartable.kt @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.broadcast + +import android.content.Context +import com.android.systemui.CoreStartable +import javax.inject.Inject + +class BroadcastDispatcherStartable @Inject constructor( + context: Context, + val broadcastDispatcher: BroadcastDispatcher +) : CoreStartable(context) { + + override fun start() { + broadcastDispatcher.initialize() + } +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/PendingRemovalStore.kt b/packages/SystemUI/src/com/android/systemui/broadcast/PendingRemovalStore.kt new file mode 100644 index 000000000000..a5d730fc5009 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/broadcast/PendingRemovalStore.kt @@ -0,0 +1,59 @@ +package com.android.systemui.broadcast + +import android.content.BroadcastReceiver +import android.os.UserHandle +import android.util.SparseSetArray +import androidx.annotation.GuardedBy +import com.android.systemui.Dumpable +import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger +import com.android.systemui.util.indentIfPossible +import java.io.PrintWriter +import javax.inject.Inject + +/** + * Store information about requests for unregistering receivers from [BroadcastDispatcher], before + * they have been completely removed from the system. + * + * This helps make unregistering a receiver a *sync* operation. + */ +class PendingRemovalStore @Inject constructor( + private val logger: BroadcastDispatcherLogger +) : Dumpable { + @GuardedBy("pendingRemoval") + private val pendingRemoval: SparseSetArray<BroadcastReceiver> = SparseSetArray() + + fun tagForRemoval(broadcastReceiver: BroadcastReceiver, userId: Int) { + logger.logTagForRemoval(userId, broadcastReceiver) + synchronized(pendingRemoval) { + pendingRemoval.add(userId, broadcastReceiver) + } + } + + fun isPendingRemoval(broadcastReceiver: BroadcastReceiver, userId: Int): Boolean { + return synchronized(pendingRemoval) { + pendingRemoval.contains(userId, broadcastReceiver) || + pendingRemoval.contains(UserHandle.USER_ALL, broadcastReceiver) + } + } + + fun clearPendingRemoval(broadcastReceiver: BroadcastReceiver, userId: Int) { + synchronized(pendingRemoval) { + pendingRemoval.remove(userId, broadcastReceiver) + } + logger.logClearedAfterRemoval(userId, broadcastReceiver) + } + + override fun dump(pw: PrintWriter, args: Array<out String>) { + synchronized(pendingRemoval) { + pw.indentIfPossible { + val size = pendingRemoval.size() + for (i in 0 until size) { + val user = pendingRemoval.keyAt(i) + print(user) + print("->") + println(pendingRemoval.get(user)) + } + } + } + } +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt index 24ce2384ab46..6b15188cdb2a 100644 --- a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt +++ b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt @@ -20,12 +20,12 @@ import android.content.BroadcastReceiver import android.content.Context import android.os.Handler import android.os.Looper -import android.os.Message import android.os.UserHandle import android.util.ArrayMap import android.util.ArraySet import android.util.Log import androidx.annotation.VisibleForTesting +import androidx.annotation.WorkerThread import com.android.internal.util.Preconditions import com.android.systemui.Dumpable import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger @@ -34,8 +34,6 @@ import java.io.PrintWriter import java.util.concurrent.Executor import java.util.concurrent.atomic.AtomicInteger -private const val MSG_REGISTER_RECEIVER = 0 -private const val MSG_UNREGISTER_RECEIVER = 1 private const val TAG = "UserBroadcastDispatcher" private const val DEBUG = false @@ -50,7 +48,8 @@ open class UserBroadcastDispatcher( private val userId: Int, private val bgLooper: Looper, private val bgExecutor: Executor, - private val logger: BroadcastDispatcherLogger + private val logger: BroadcastDispatcherLogger, + private val removalPendingStore: PendingRemovalStore ) : Dumpable { companion object { @@ -60,16 +59,6 @@ open class UserBroadcastDispatcher( val index = AtomicInteger(0) } - private val bgHandler = object : Handler(bgLooper) { - override fun handleMessage(msg: Message) { - when (msg.what) { - MSG_REGISTER_RECEIVER -> handleRegisterReceiver(msg.obj as ReceiverData, msg.arg1) - MSG_UNREGISTER_RECEIVER -> handleUnregisterReceiver(msg.obj as BroadcastReceiver) - else -> Unit - } - } - } - // Used for key in actionsToActionsReceivers internal data class ReceiverProperties( val action: String, @@ -77,6 +66,8 @@ open class UserBroadcastDispatcher( val permission: String? ) + private val bgHandler = Handler(bgLooper) + // Only modify in BG thread @VisibleForTesting internal val actionsToActionsReceivers = ArrayMap<ReceiverProperties, ActionReceiver>() @@ -92,19 +83,21 @@ open class UserBroadcastDispatcher( /** * Register a [ReceiverData] for this user. */ + @WorkerThread fun registerReceiver(receiverData: ReceiverData, flags: Int) { - bgHandler.obtainMessage(MSG_REGISTER_RECEIVER, flags, 0, receiverData).sendToTarget() + handleRegisterReceiver(receiverData, flags) } /** * Unregister a given [BroadcastReceiver] for this user. */ + @WorkerThread fun unregisterReceiver(receiver: BroadcastReceiver) { - bgHandler.obtainMessage(MSG_UNREGISTER_RECEIVER, receiver).sendToTarget() + handleUnregisterReceiver(receiver) } private fun handleRegisterReceiver(receiverData: ReceiverData, flags: Int) { - Preconditions.checkState(bgHandler.looper.isCurrentThread, + Preconditions.checkState(bgLooper.isCurrentThread, "This method should only be called from BG thread") if (DEBUG) Log.w(TAG, "Register receiver: ${receiverData.receiver}") receiverToActions @@ -151,12 +144,13 @@ open class UserBroadcastDispatcher( } }, bgExecutor, - logger + logger, + removalPendingStore::isPendingRemoval ) } private fun handleUnregisterReceiver(receiver: BroadcastReceiver) { - Preconditions.checkState(bgHandler.looper.isCurrentThread, + Preconditions.checkState(bgLooper.isCurrentThread, "This method should only be called from BG thread") if (DEBUG) Log.w(TAG, "Unregister receiver: $receiver") receiverToActions.getOrDefault(receiver, mutableSetOf()).forEach { diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt b/packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt index 8da651991072..5b3a982ab5e2 100644 --- a/packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt @@ -87,6 +87,26 @@ class BroadcastDispatcherLogger @Inject constructor( }) } + fun logTagForRemoval(user: Int, receiver: BroadcastReceiver) { + val receiverString = receiver.toString() + log(DEBUG, { + int1 = user + str1 = receiverString + }, { + "Receiver $str1 tagged for removal from user $int1" + }) + } + + fun logClearedAfterRemoval(user: Int, receiver: BroadcastReceiver) { + val receiverString = receiver.toString() + log(DEBUG, { + int1 = user + str1 = receiverString + }, { + "Receiver $str1 has been completely removed for user $int1" + }) + } + fun logReceiverUnregistered(user: Int, receiver: BroadcastReceiver) { val receiverString = receiver.toString() log(INFO, { diff --git a/packages/SystemUI/src/com/android/systemui/dagger/AndroidInternalsModule.java b/packages/SystemUI/src/com/android/systemui/dagger/AndroidInternalsModule.java new file mode 100644 index 000000000000..48c54bca69ee --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/dagger/AndroidInternalsModule.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.dagger; + +import android.content.Context; + +import com.android.internal.logging.MetricsLogger; +import com.android.internal.util.NotificationMessagingUtil; +import com.android.internal.widget.LockPatternUtils; + +import dagger.Module; +import dagger.Provides; + +/** + * Provides items imported from com.android.internal. + */ +@Module +public class AndroidInternalsModule { + /** */ + @Provides + @SysUISingleton + public LockPatternUtils provideLockPatternUtils(Context context) { + return new LockPatternUtils(context); + } + + /** */ + @Provides + @SysUISingleton + public MetricsLogger provideMetricsLogger() { + return new MetricsLogger(); + } + + /** */ + @Provides + public NotificationMessagingUtil provideNotificationMessagingUtil(Context context) { + return new NotificationMessagingUtil(context); + } + +} diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java index 1653e0adadb5..fb016911f913 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java @@ -29,8 +29,10 @@ import com.android.systemui.sensorprivacy.television.TvUnblockSensorActivity; import com.android.systemui.settings.brightness.BrightnessDialog; import com.android.systemui.statusbar.tv.notifications.TvNotificationPanelActivity; import com.android.systemui.tuner.TunerActivity; +import com.android.systemui.usb.UsbConfirmActivity; import com.android.systemui.usb.UsbDebuggingActivity; import com.android.systemui.usb.UsbDebuggingSecondaryUserActivity; +import com.android.systemui.usb.UsbPermissionActivity; import com.android.systemui.user.CreateUserActivity; import dagger.Binds; @@ -80,6 +82,18 @@ public abstract class DefaultActivityBinder { public abstract Activity bindUsbDebuggingSecondaryUserActivity( UsbDebuggingSecondaryUserActivity activity); + /** Inject into UsbPermissionActivity. */ + @Binds + @IntoMap + @ClassKey(UsbPermissionActivity.class) + public abstract Activity bindUsbPermissionActivity(UsbPermissionActivity activity); + + /** Inject into UsbConfirmActivity. */ + @Binds + @IntoMap + @ClassKey(UsbConfirmActivity.class) + public abstract Activity bindUsbConfirmActivity(UsbConfirmActivity activity); + /** Inject into CreateUserActivity. */ @Binds @IntoMap diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java index fa2384268b15..31ad36fb21d8 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java @@ -16,279 +16,24 @@ package com.android.systemui.dagger; -import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME; - -import android.annotation.Nullable; -import android.annotation.SuppressLint; -import android.app.INotificationManager; -import android.content.Context; -import android.content.SharedPreferences; -import android.content.om.OverlayManager; -import android.hardware.display.AmbientDisplayConfiguration; -import android.hardware.display.ColorDisplayManager; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.ServiceManager; -import android.os.UserHandle; -import android.view.Choreographer; -import android.view.IWindowManager; -import android.view.LayoutInflater; - -import com.android.internal.logging.MetricsLogger; -import com.android.internal.util.NotificationMessagingUtil; -import com.android.internal.widget.LockPatternUtils; -import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.keyguard.ViewMediatorCallback; -import com.android.settingslib.bluetooth.LocalBluetoothManager; -import com.android.systemui.Prefs; -import com.android.systemui.R; -import com.android.systemui.accessibility.AccessibilityButtonModeObserver; -import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver; -import com.android.systemui.accessibility.ModeSwitchesController; -import com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuController; -import com.android.systemui.broadcast.BroadcastDispatcher; -import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger; -import com.android.systemui.dagger.qualifiers.Background; -import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.doze.AlwaysOnDisplayPolicy; -import com.android.systemui.dump.DumpManager; -import com.android.systemui.keyguard.KeyguardViewMediator; -import com.android.systemui.qs.ReduceBrightColorsController; -import com.android.systemui.settings.UserTracker; -import com.android.systemui.shared.system.ActivityManagerWrapper; -import com.android.systemui.shared.system.DevicePolicyManagerWrapper; -import com.android.systemui.shared.system.TaskStackChangeListeners; -import com.android.systemui.shared.system.WindowManagerWrapper; -import com.android.systemui.statusbar.connectivity.NetworkController; -import com.android.systemui.statusbar.phone.AutoHideController; -import com.android.systemui.statusbar.phone.ConfigurationControllerImpl; -import com.android.systemui.statusbar.policy.ConfigurationController; -import com.android.systemui.statusbar.policy.DataSaverController; -import com.android.systemui.theme.ThemeOverlayApplier; -import com.android.systemui.util.leak.LeakDetector; -import com.android.systemui.util.settings.SecureSettings; - -import java.util.concurrent.Executor; - -import javax.inject.Named; +import com.android.systemui.broadcast.BroadcastDispatcherModule; +import com.android.systemui.theme.ThemeModule; +import com.android.systemui.util.leak.LeakModule; import dagger.Module; -import dagger.Provides; /** - * Provides dependencies for the root component of sysui injection. - * - * Only SystemUI owned classes and instances should go in here. Other, framework-owned classes - * should go in {@link FrameworkServicesModule}. - * - * See SystemUI/docs/dagger.md + * @deprecated This module is going away. Don't put anything in here. */ -@Module(includes = {NightDisplayListenerModule.class}) +@Deprecated +@Module(includes = { + AndroidInternalsModule.class, + BroadcastDispatcherModule.class, + LeakModule.class, + NightDisplayListenerModule.class, + SharedLibraryModule.class, + SettingsLibraryModule.class, + ThemeModule.class +}) public class DependencyProvider { - - /** */ - @Provides - @SysUISingleton - @Named(TIME_TICK_HANDLER_NAME) - public Handler provideTimeTickHandler() { - HandlerThread thread = new HandlerThread("TimeTick"); - thread.start(); - return new Handler(thread.getLooper()); - } - - /** */ - @Provides - @Main - public SharedPreferences provideSharePreferences(Context context) { - return Prefs.get(context); - } - - /** */ - @Provides - public AmbientDisplayConfiguration provideAmbientDisplayConfiguration(Context context) { - return new AmbientDisplayConfiguration(context); - } - - /** */ - @Provides - public Handler provideHandler() { - return new Handler(); - } - - /** */ - @Provides - @SysUISingleton - public DataSaverController provideDataSaverController(NetworkController networkController) { - return networkController.getDataSaverController(); - } - - @Provides - @SysUISingleton - public INotificationManager provideINotificationManager() { - return INotificationManager.Stub.asInterface( - ServiceManager.getService(Context.NOTIFICATION_SERVICE)); - } - - /** */ - @Provides - @SysUISingleton - public LayoutInflater providerLayoutInflater(Context context) { - return LayoutInflater.from(context); - } - - /** */ - @Provides - @SysUISingleton - public LeakDetector provideLeakDetector(DumpManager dumpManager) { - return LeakDetector.create(dumpManager); - } - - @SuppressLint("MissingPermission") - @SysUISingleton - @Provides - @Nullable - static LocalBluetoothManager provideLocalBluetoothController(Context context, - @Background Handler bgHandler) { - return LocalBluetoothManager.create(context, bgHandler, UserHandle.ALL); - } - - /** */ - @Provides - @SysUISingleton - public MetricsLogger provideMetricsLogger() { - return new MetricsLogger(); - } - - /** */ - @SysUISingleton - @Provides - static ThemeOverlayApplier provideThemeOverlayManager(Context context, - @Background Executor bgExecutor, - @Main Executor mainExecutor, - OverlayManager overlayManager, - DumpManager dumpManager) { - return new ThemeOverlayApplier(overlayManager, bgExecutor, mainExecutor, - context.getString(R.string.launcher_overlayable_package), - context.getString(R.string.themepicker_overlayable_package), dumpManager); - } - - /** */ - @Provides - @SysUISingleton - public AccessibilityFloatingMenuController provideAccessibilityFloatingMenuController( - Context context, AccessibilityButtonTargetsObserver accessibilityButtonTargetsObserver, - AccessibilityButtonModeObserver accessibilityButtonModeObserver, - KeyguardUpdateMonitor keyguardUpdateMonitor) { - return new AccessibilityFloatingMenuController(context, accessibilityButtonTargetsObserver, - accessibilityButtonModeObserver, keyguardUpdateMonitor); - } - - /** */ - @Provides - @SysUISingleton - public ConfigurationController provideConfigurationController(Context context) { - return new ConfigurationControllerImpl(context); - } - - /** */ - @SysUISingleton - @Provides - public AutoHideController provideAutoHideController(Context context, - @Main Handler mainHandler, IWindowManager iWindowManager) { - return new AutoHideController(context, mainHandler, iWindowManager); - } - - /** */ - @SysUISingleton - @Provides - public ReduceBrightColorsController provideReduceBrightColorsListener( - @Background Handler bgHandler, UserTracker userTracker, - ColorDisplayManager colorDisplayManager, SecureSettings secureSettings) { - return new ReduceBrightColorsController(userTracker, bgHandler, - colorDisplayManager, secureSettings); - } - - @Provides - @SysUISingleton - public ActivityManagerWrapper provideActivityManagerWrapper() { - return ActivityManagerWrapper.getInstance(); - } - - /** */ - @Provides - @SysUISingleton - public TaskStackChangeListeners provideTaskStackChangeListeners() { - return TaskStackChangeListeners.getInstance(); - } - - /** Provides and initializes the {#link BroadcastDispatcher} for SystemUI */ - @Provides - @SysUISingleton - public BroadcastDispatcher providesBroadcastDispatcher( - Context context, - @Background Looper backgroundLooper, - @Background Executor backgroundExecutor, - DumpManager dumpManager, - BroadcastDispatcherLogger logger, - UserTracker userTracker - ) { - BroadcastDispatcher bD = new BroadcastDispatcher(context, backgroundLooper, - backgroundExecutor, dumpManager, logger, userTracker); - bD.initialize(); - return bD; - } - - /** */ - @Provides - @SysUISingleton - public DevicePolicyManagerWrapper provideDevicePolicyManagerWrapper() { - return DevicePolicyManagerWrapper.getInstance(); - } - - /** */ - @Provides - @SysUISingleton - public LockPatternUtils provideLockPatternUtils(Context context) { - return new LockPatternUtils(context); - } - - /** */ - @Provides - @SysUISingleton - public AlwaysOnDisplayPolicy provideAlwaysOnDisplayPolicy(Context context) { - return new AlwaysOnDisplayPolicy(context); - } - - /***/ - @Provides - public NotificationMessagingUtil provideNotificationMessagingUtil(Context context) { - return new NotificationMessagingUtil(context); - } - - /** */ - @Provides - public ViewMediatorCallback providesViewMediatorCallback(KeyguardViewMediator viewMediator) { - return viewMediator.getViewMediatorCallback(); - } - - /** */ - @Provides - public WindowManagerWrapper providesWindowManagerWrapper() { - return WindowManagerWrapper.getInstance(); - } - - /** */ - @Provides - @SysUISingleton - public Choreographer providesChoreographer() { - return Choreographer.getInstance(); - } - - /** */ - @Provides - @SysUISingleton - public ModeSwitchesController providesModeSwitchesController(Context context) { - return new ModeSwitchesController(context); - } } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java index b172e92871ce..e512b7cf3a20 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java @@ -22,6 +22,7 @@ import android.app.ActivityTaskManager; import android.app.AlarmManager; import android.app.IActivityManager; import android.app.IActivityTaskManager; +import android.app.INotificationManager; import android.app.IWallpaperManager; import android.app.KeyguardManager; import android.app.NotificationManager; @@ -35,6 +36,7 @@ import android.app.trust.TrustManager; import android.content.ClipboardManager; import android.content.ContentResolver; import android.content.Context; +import android.content.SharedPreferences; import android.content.om.OverlayManager; import android.content.pm.IPackageManager; import android.content.pm.LauncherApps; @@ -44,6 +46,7 @@ import android.content.res.Resources; import android.hardware.SensorManager; import android.hardware.SensorPrivacyManager; import android.hardware.devicestate.DeviceStateManager; +import android.hardware.display.AmbientDisplayConfiguration; import android.hardware.display.ColorDisplayManager; import android.hardware.display.DisplayManager; import android.hardware.face.FaceManager; @@ -68,8 +71,10 @@ import android.telecom.TelecomManager; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.view.Choreographer; import android.view.CrossWindowBlurListeners; import android.view.IWindowManager; +import android.view.LayoutInflater; import android.view.ViewConfiguration; import android.view.WindowManager; import android.view.WindowManagerGlobal; @@ -82,6 +87,7 @@ import com.android.internal.appwidget.IAppWidgetService; import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.util.LatencyTracker; +import com.android.systemui.Prefs; import com.android.systemui.dagger.qualifiers.DisplayId; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.shared.system.PackageManagerWrapper; @@ -116,6 +122,12 @@ public class FrameworkServicesModule { return context.getSystemService(AlarmManager.class); } + /** */ + @Provides + public AmbientDisplayConfiguration provideAmbientDisplayConfiguration(Context context) { + return new AmbientDisplayConfiguration(context); + } + @Provides @Singleton static AudioManager provideAudioManager(Context context) { @@ -128,6 +140,13 @@ public class FrameworkServicesModule { return context.getSystemService(CaptioningManager.class); } + /** */ + @Provides + @Singleton + public Choreographer providesChoreographer() { + return Choreographer.getInstance(); + } + @Provides @Singleton static ColorDisplayManager provideColorDisplayManager(Context context) { @@ -293,6 +312,13 @@ public class FrameworkServicesModule { return context.getSystemService(LauncherApps.class); } + /** */ + @Provides + @Singleton + public LayoutInflater providerLayoutInflater(Context context) { + return LayoutInflater.from(context); + } + @Provides static MediaRouter2Manager provideMediaRouter2Manager(Context context) { return MediaRouter2Manager.getInstance(context); @@ -315,6 +341,14 @@ public class FrameworkServicesModule { return context.getSystemService(NotificationManager.class); } + /** */ + @Provides + @Singleton + public INotificationManager provideINotificationManager() { + return INotificationManager.Stub.asInterface( + ServiceManager.getService(Context.NOTIFICATION_SERVICE)); + } + @Provides @Singleton static PackageManager providePackageManager(Context context) { @@ -336,6 +370,13 @@ public class FrameworkServicesModule { /** */ @Provides + @Main + public SharedPreferences provideSharePreferences(Context context) { + return Prefs.get(context); + } + + /** */ + @Provides @Singleton static UiModeManager provideUiModeManager(Context context) { return context.getSystemService(UiModeManager.class); @@ -490,5 +531,4 @@ public class FrameworkServicesModule { static SafetyCenterManager provideSafetyCenterManager(Context context) { return context.getSystemService(SafetyCenterManager.class); } - } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SettingsLibraryModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SettingsLibraryModule.java new file mode 100644 index 000000000000..14626e1e6515 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/dagger/SettingsLibraryModule.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.dagger; + +import android.annotation.Nullable; +import android.annotation.SuppressLint; +import android.content.Context; +import android.os.Handler; +import android.os.UserHandle; + +import com.android.settingslib.bluetooth.LocalBluetoothManager; +import com.android.systemui.dagger.qualifiers.Background; + +import dagger.Module; +import dagger.Provides; + +/** */ +@Module +public class SettingsLibraryModule { + + /** */ + @SuppressLint("MissingPermission") + @SysUISingleton + @Provides + @Nullable + static LocalBluetoothManager provideLocalBluetoothController(Context context, + @Background Handler bgHandler) { + return LocalBluetoothManager.create(context, bgHandler, UserHandle.ALL); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SharedLibraryModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SharedLibraryModule.java new file mode 100644 index 000000000000..be156157fb72 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/dagger/SharedLibraryModule.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.dagger; + +import com.android.systemui.shared.system.ActivityManagerWrapper; +import com.android.systemui.shared.system.DevicePolicyManagerWrapper; +import com.android.systemui.shared.system.TaskStackChangeListeners; +import com.android.systemui.shared.system.WindowManagerWrapper; + +import dagger.Module; +import dagger.Provides; + +/** */ +@Module +public class SharedLibraryModule { + + /** */ + @Provides + @SysUISingleton + public ActivityManagerWrapper provideActivityManagerWrapper() { + return ActivityManagerWrapper.getInstance(); + } + + /** */ + @Provides + @SysUISingleton + public DevicePolicyManagerWrapper provideDevicePolicyManagerWrapper() { + return DevicePolicyManagerWrapper.getInstance(); + } + + /** */ + @Provides + @SysUISingleton + public TaskStackChangeListeners provideTaskStackChangeListeners() { + return TaskStackChangeListeners.getInstance(); + } + + /** */ + @Provides + public WindowManagerWrapper providesWindowManagerWrapper() { + return WindowManagerWrapper.getInstance(); + } + +} diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index 7b65f453815c..bbeb66c5af52 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -29,6 +29,7 @@ import com.android.systemui.BootCompleteCacheImpl; import com.android.systemui.SystemUIFactory; import com.android.systemui.appops.dagger.AppOpsModule; import com.android.systemui.assist.AssistModule; +import com.android.systemui.biometrics.AlternateUdfpsTouchProvider; import com.android.systemui.biometrics.UdfpsHbmProvider; import com.android.systemui.biometrics.dagger.BiometricsModule; import com.android.systemui.classifier.FalsingModule; @@ -182,6 +183,9 @@ public abstract class SystemUIModule { @BindsOptionalOf abstract UdfpsHbmProvider optionalUdfpsHbmProvider(); + @BindsOptionalOf + abstract AlternateUdfpsTouchProvider optionalUdfpsTouchProvider(); + @SysUISingleton @Binds abstract SystemClock bindSystemClock(SystemClockImpl systemClock); diff --git a/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt b/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt index 3543bb4ab9e9..03ee8b11ab41 100644 --- a/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt @@ -15,8 +15,8 @@ */ package com.android.systemui.decor +import android.content.Context import android.view.DisplayCutout -import android.view.LayoutInflater import android.view.Surface import android.view.View import android.view.ViewGroup @@ -38,9 +38,20 @@ abstract class DecorProvider { /** The aligned bounds for the view which is created through inflateView() */ abstract val alignedBounds: List<Int> + /** + * Called when res info changed. + * Child provider needs to implement it if its view needs to be updated. + */ + abstract fun onReloadResAndMeasure( + view: View, + reloadToken: Int, + @Surface.Rotation rotation: Int, + displayUniqueId: String? = null + ) + /** Inflate view into parent as current rotation */ abstract fun inflateView( - inflater: LayoutInflater, + context: Context, parent: ViewGroup, @Surface.Rotation rotation: Int ): View diff --git a/packages/SystemUI/src/com/android/systemui/decor/DecorProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/DecorProviderFactory.kt index c60cad8419d2..cc4096fb3b19 100644 --- a/packages/SystemUI/src/com/android/systemui/decor/DecorProviderFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/decor/DecorProviderFactory.kt @@ -19,4 +19,5 @@ package com.android.systemui.decor abstract class DecorProviderFactory { abstract val providers: List<DecorProvider> abstract val hasProviders: Boolean + abstract fun onDisplayUniqueIdChanged(displayUniqueId: String?) }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt b/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt index 9f8679cdea4a..d775ad39a5c3 100644 --- a/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt +++ b/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt @@ -16,31 +16,25 @@ package com.android.systemui.decor import android.annotation.IdRes -import android.view.DisplayCutout -import android.view.LayoutInflater +import android.content.Context import android.view.Surface import android.view.View import android.view.ViewGroup -import com.android.systemui.R -import java.util.HashMap - -class OverlayWindow(private val layoutInflater: LayoutInflater, private val pos: Int) { - - private val layoutId: Int - get() { - return if (pos == DisplayCutout.BOUNDS_POSITION_LEFT || - pos == DisplayCutout.BOUNDS_POSITION_TOP) { - R.layout.rounded_corners_top - } else { - R.layout.rounded_corners_bottom - } - } +import com.android.systemui.RegionInterceptingFrameLayout + +class OverlayWindow(private val context: Context) { - val rootView = layoutInflater.inflate(layoutId, null) as ViewGroup - private val viewProviderMap: MutableMap<Int, Pair<View, DecorProvider>> = HashMap() + val rootView = RegionInterceptingFrameLayout(context) as ViewGroup + private val viewProviderMap = mutableMapOf<Int, Pair<View, DecorProvider>>() - fun addDecorProvider(decorProvider: DecorProvider, @Surface.Rotation rotation: Int) { - val view = decorProvider.inflateView(layoutInflater, rootView, rotation) + val viewIds: List<Int> + get() = viewProviderMap.keys.toList() + + fun addDecorProvider( + decorProvider: DecorProvider, + @Surface.Rotation rotation: Int + ) { + val view = decorProvider.inflateView(context, rootView, rotation) viewProviderMap[decorProvider.viewId] = Pair(view, decorProvider) } @@ -56,4 +50,54 @@ class OverlayWindow(private val layoutInflater: LayoutInflater, private val pos: viewProviderMap.remove(id) } } + + /** + * Remove views which does not been found in expectExistViewIds + */ + fun removeRedundantViews(expectExistViewIds: IntArray?) { + viewIds.forEach { + if (expectExistViewIds == null || !(expectExistViewIds.contains(it))) { + removeView(it) + } + } + } + + /** + * Check that newProviders is the same list with viewProviderMap. + */ + fun hasSameProviders(newProviders: List<DecorProvider>): Boolean { + return (newProviders.size == viewProviderMap.size) && + newProviders.all { getView(it.viewId) != null } + } + + /** + * Apply new configuration info into views. + * @param filterIds target view ids. Apply to all if null. + * @param rotation current or new rotation direction. + * @param displayUniqueId new displayUniqueId if any. + */ + fun onReloadResAndMeasure( + filterIds: Array<Int>? = null, + reloadToken: Int, + @Surface.Rotation rotation: Int, + displayUniqueId: String? = null + ) { + filterIds?.forEach { id -> + viewProviderMap[id]?.let { + it.second.onReloadResAndMeasure( + view = it.first, + reloadToken = reloadToken, + displayUniqueId = displayUniqueId, + rotation = rotation) + } + } ?: run { + viewProviderMap.values.forEach { + it.second.onReloadResAndMeasure( + view = it.first, + reloadToken = reloadToken, + displayUniqueId = displayUniqueId, + rotation = rotation) + } + } + } }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt index 7afd7e0eedc5..d16d9604c002 100644 --- a/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt @@ -16,6 +16,7 @@ package com.android.systemui.decor +import android.content.Context import android.content.res.Resources import android.view.DisplayCutout import android.view.LayoutInflater @@ -38,6 +39,10 @@ class PrivacyDotDecorProviderFactory @Inject constructor( override val hasProviders: Boolean get() = isPrivacyDotEnabled + override fun onDisplayUniqueIdChanged(displayUniqueId: String?) { + // Do nothing for privacy dot + } + override val providers: List<DecorProvider> get() { return if (hasProviders) { @@ -76,12 +81,21 @@ class PrivacyDotCornerDecorProviderImpl( private val layoutId: Int ) : CornerDecorProvider() { + override fun onReloadResAndMeasure( + view: View, + reloadToken: Int, + rotation: Int, + displayUniqueId: String? + ) { + // Do nothing here because it is handled inside PrivacyDotViewController + } + override fun inflateView( - inflater: LayoutInflater, + context: Context, parent: ViewGroup, @Surface.Rotation rotation: Int ): View { - inflater.inflate(layoutId, parent, true) + LayoutInflater.from(context).inflate(layoutId, parent, true) return parent.getChildAt(parent.childCount - 1 /* latest new added child */) } } diff --git a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderFactory.kt new file mode 100644 index 000000000000..a4f7a586ab97 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderFactory.kt @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.decor + +import android.view.DisplayCutout +import com.android.systemui.R + +class RoundedCornerDecorProviderFactory( + private val roundedCornerResDelegate: RoundedCornerResDelegate +) : DecorProviderFactory() { + + override val hasProviders: Boolean + get() = roundedCornerResDelegate.run { + // We don't consider isMultipleRadius here because it makes no sense if size is zero. + topRoundedSize.width > 0 || bottomRoundedSize.width > 0 + } + + override fun onDisplayUniqueIdChanged(displayUniqueId: String?) { + roundedCornerResDelegate.updateDisplayUniqueId(displayUniqueId, null) + } + + override val providers: List<DecorProvider> + get() { + val hasTop = roundedCornerResDelegate.topRoundedSize.width > 0 + val hasBottom = roundedCornerResDelegate.bottomRoundedSize.width > 0 + return when { + hasTop && hasBottom -> listOf( + RoundedCornerDecorProviderImpl( + viewId = R.id.rounded_corner_top_left, + alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP, + alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT, + roundedCornerResDelegate = roundedCornerResDelegate), + RoundedCornerDecorProviderImpl( + viewId = R.id.rounded_corner_top_right, + alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP, + alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT, + roundedCornerResDelegate = roundedCornerResDelegate), + RoundedCornerDecorProviderImpl( + viewId = R.id.rounded_corner_bottom_left, + alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM, + alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT, + roundedCornerResDelegate = roundedCornerResDelegate), + RoundedCornerDecorProviderImpl( + viewId = R.id.rounded_corner_bottom_right, + alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM, + alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT, + roundedCornerResDelegate = roundedCornerResDelegate) + ) + hasTop -> listOf( + RoundedCornerDecorProviderImpl( + viewId = R.id.rounded_corner_top_left, + alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP, + alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT, + roundedCornerResDelegate = roundedCornerResDelegate), + RoundedCornerDecorProviderImpl( + viewId = R.id.rounded_corner_top_right, + alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP, + alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT, + roundedCornerResDelegate = roundedCornerResDelegate) + ) + hasBottom -> listOf( + RoundedCornerDecorProviderImpl( + viewId = R.id.rounded_corner_bottom_left, + alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM, + alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT, + roundedCornerResDelegate = roundedCornerResDelegate), + RoundedCornerDecorProviderImpl( + viewId = R.id.rounded_corner_bottom_right, + alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM, + alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT, + roundedCornerResDelegate = roundedCornerResDelegate) + ) + else -> emptyList() + } + } +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt new file mode 100644 index 000000000000..90ff950406b4 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.decor + +import android.content.Context +import android.view.DisplayCutout +import android.view.Gravity +import android.view.Surface +import android.view.View +import android.view.ViewGroup +import android.widget.FrameLayout +import android.widget.ImageView +import com.android.systemui.R + +class RoundedCornerDecorProviderImpl( + override val viewId: Int, + @DisplayCutout.BoundsPosition override val alignedBound1: Int, + @DisplayCutout.BoundsPosition override val alignedBound2: Int, + private val roundedCornerResDelegate: RoundedCornerResDelegate +) : CornerDecorProvider() { + + private val isTop = alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP) + + override fun inflateView( + context: Context, + parent: ViewGroup, + @Surface.Rotation rotation: Int + ): View { + return ImageView(context).also { view -> + // View + view.id = viewId + initView(view, rotation) + + // LayoutParams + val layoutSize = if (isTop) { + roundedCornerResDelegate.topRoundedSize + } else { + roundedCornerResDelegate.bottomRoundedSize + } + val params = FrameLayout.LayoutParams( + layoutSize.width, + layoutSize.height, + alignedBound1.toLayoutGravity(rotation) or + alignedBound2.toLayoutGravity(rotation)) + + // AddView + parent.addView(view, params) + } + } + + private fun initView(view: ImageView, @Surface.Rotation rotation: Int) { + view.setRoundedCornerImage(roundedCornerResDelegate, isTop) + view.adjustRotation(alignedBounds, rotation) + view.setColorFilter(IMAGE_TINT_COLOR) + } + + override fun onReloadResAndMeasure( + view: View, + reloadToken: Int, + @Surface.Rotation rotation: Int, + displayUniqueId: String? + ) { + roundedCornerResDelegate.updateDisplayUniqueId(displayUniqueId, reloadToken) + + initView((view as ImageView), rotation) + + val layoutSize = if (isTop) { + roundedCornerResDelegate.topRoundedSize + } else { + roundedCornerResDelegate.bottomRoundedSize + } + (view.layoutParams as FrameLayout.LayoutParams).let { + it.width = layoutSize.width + it.height = layoutSize.height + it.gravity = alignedBound1.toLayoutGravity(rotation) or + alignedBound2.toLayoutGravity(rotation) + view.setLayoutParams(it) + } + } +} + +private const val IMAGE_TINT_COLOR: Int = 0xFF000000.toInt() + +@DisplayCutout.BoundsPosition +private fun Int.toLayoutGravity(@Surface.Rotation rotation: Int): Int = when (rotation) { + Surface.ROTATION_0 -> when (this) { + DisplayCutout.BOUNDS_POSITION_LEFT -> Gravity.LEFT + DisplayCutout.BOUNDS_POSITION_TOP -> Gravity.TOP + DisplayCutout.BOUNDS_POSITION_RIGHT -> Gravity.RIGHT + else /* DisplayCutout.BOUNDS_POSITION_BOTTOM */ -> Gravity.BOTTOM + } + Surface.ROTATION_90 -> when (this) { + DisplayCutout.BOUNDS_POSITION_LEFT -> Gravity.BOTTOM + DisplayCutout.BOUNDS_POSITION_TOP -> Gravity.LEFT + DisplayCutout.BOUNDS_POSITION_RIGHT -> Gravity.TOP + else /* DisplayCutout.BOUNDS_POSITION_BOTTOM */ -> Gravity.LEFT + } + Surface.ROTATION_270 -> when (this) { + DisplayCutout.BOUNDS_POSITION_LEFT -> Gravity.TOP + DisplayCutout.BOUNDS_POSITION_TOP -> Gravity.RIGHT + DisplayCutout.BOUNDS_POSITION_RIGHT -> Gravity.BOTTOM + else /* DisplayCutout.BOUNDS_POSITION_BOTTOM */ -> Gravity.LEFT + } + else /* Surface.ROTATION_180 */ -> when (this) { + DisplayCutout.BOUNDS_POSITION_LEFT -> Gravity.RIGHT + DisplayCutout.BOUNDS_POSITION_TOP -> Gravity.BOTTOM + DisplayCutout.BOUNDS_POSITION_RIGHT -> Gravity.LEFT + else /* DisplayCutout.BOUNDS_POSITION_BOTTOM */ -> Gravity.TOP + } +} + +private fun ImageView.setRoundedCornerImage( + resDelegate: RoundedCornerResDelegate, + isTop: Boolean +) { + val drawable = if (isTop) + resDelegate.topRoundedDrawable + else + resDelegate.bottomRoundedDrawable + + if (drawable != null) { + setImageDrawable(drawable) + } else { + setImageResource( + if (isTop) + R.drawable.rounded_corner_top + else + R.drawable.rounded_corner_bottom + ) + } +} + +/** + * Configures the rounded corner drawable's view matrix based on the gravity. + * + * The gravity describes which corner to configure for, and the drawable we are rotating is assumed + * to be oriented for the top-left corner of the device regardless of the target corner. + * Therefore we need to rotate 180 degrees to get a bottom-left corner, and mirror in the x- or + * y-axis for the top-right and bottom-left corners. + */ +private fun ImageView.adjustRotation(alignedBounds: List<Int>, @Surface.Rotation rotation: Int) { + var newRotation = 0F + var newScaleX = 1F + var newScaleY = 1F + + val isTop = alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP) + val isLeft = alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_LEFT) + when (rotation) { + Surface.ROTATION_0 -> when { + isTop && isLeft -> {} + isTop && !isLeft -> { newScaleX = -1F } + !isTop && isLeft -> { newScaleY = -1F } + else /* !isTop && !isLeft */ -> { newRotation = 180F } + } + Surface.ROTATION_90 -> when { + isTop && isLeft -> { newScaleY = -1F } + isTop && !isLeft -> {} + !isTop && isLeft -> { newRotation = 180F } + else /* !isTop && !isLeft */ -> { newScaleX = -1F } + } + Surface.ROTATION_270 -> when { + isTop && isLeft -> { newScaleX = -1F } + isTop && !isLeft -> { newRotation = 180F } + !isTop && isLeft -> {} + else /* !isTop && !isLeft */ -> { newScaleY = -1F } + } + else /* Surface.ROTATION_180 */ -> when { + isTop && isLeft -> { newRotation = 180F } + isTop && !isLeft -> { newScaleY = -1F } + !isTop && isLeft -> { newScaleX = -1F } + else /* !isTop && !isLeft */ -> {} + } + } + + this.rotation = newRotation + this.scaleX = newScaleX + this.scaleY = newScaleY +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt index ed175ef7a095..c2bab269d396 100644 --- a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt +++ b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt @@ -35,6 +35,8 @@ class RoundedCornerResDelegate( private val density: Float get() = res.displayMetrics.density + private var reloadToken: Int = 0 + var isMultipleRadius: Boolean = false private set @@ -59,12 +61,26 @@ class RoundedCornerResDelegate( reloadMeasures() } - fun reloadAll(newDisplayUniqueId: String?) { - displayUniqueId = newDisplayUniqueId + private fun reloadAll(newReloadToken: Int) { + if (reloadToken == newReloadToken) { + return + } + reloadToken = newReloadToken reloadRes() reloadMeasures() } + fun updateDisplayUniqueId(newDisplayUniqueId: String?, newReloadToken: Int?) { + if (displayUniqueId != newDisplayUniqueId) { + displayUniqueId = newDisplayUniqueId + newReloadToken ?.let { reloadToken = it } + reloadRes() + reloadMeasures() + } else { + newReloadToken?.let { reloadAll(it) } + } + } + private fun reloadRes() { val configIdx = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId) isMultipleRadius = getIsMultipleRadius(configIdx) @@ -122,7 +138,11 @@ class RoundedCornerResDelegate( } } - fun updateTuningSizeFactor(factor: Int) { + fun updateTuningSizeFactor(factor: Int?, newReloadToken: Int) { + if (reloadToken == newReloadToken) { + return + } + reloadToken = newReloadToken reloadMeasures(factor) } diff --git a/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java b/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java index 735b3cd4b824..55df7792e2e6 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java @@ -29,11 +29,15 @@ import android.util.KeyValueListParser; import android.util.Log; import com.android.systemui.R; +import com.android.systemui.dagger.SysUISingleton; + +import javax.inject.Inject; /** * Class to store the policy for AOD, which comes from * {@link android.provider.Settings.Global} */ +@SysUISingleton public class AlwaysOnDisplayPolicy { public static final String TAG = "AlwaysOnDisplayPolicy"; @@ -130,6 +134,7 @@ public class AlwaysOnDisplayPolicy { private final Context mContext; private SettingsObserver mSettingsObserver; + @Inject public AlwaysOnDisplayPolicy(Context context) { context = context.getApplicationContext(); mContext = context; diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java index 0024a460136e..83220cab7149 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java @@ -147,10 +147,12 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi setLightSensorEnabled(true); break; case DOZE: - case DOZE_AOD_PAUSED: setLightSensorEnabled(false); resetBrightnessToDefault(); break; + case DOZE_AOD_PAUSED: + setLightSensorEnabled(false); + break; case FINISH: onDestroy(); break; diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java index fb1af8b66b91..74949d094e33 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java @@ -16,7 +16,7 @@ package com.android.systemui.dreams; -import static com.android.keyguard.BouncerPanelExpansionCalculator.getBackScrimScaledExpansion; +import static com.android.keyguard.BouncerPanelExpansionCalculator.aboutToShowBouncerProgress; import static com.android.keyguard.BouncerPanelExpansionCalculator.getDreamAlphaScaledExpansion; import static com.android.keyguard.BouncerPanelExpansionCalculator.getDreamYPositionScaledExpansion; import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset; @@ -217,19 +217,19 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve mBlurUtils.applyBlur(mView.getViewRootImpl(), (int) mBlurUtils.blurRadiusOfRatio( - 1 - getBackScrimScaledExpansion(bouncerHideAmount)), false); + 1 - aboutToShowBouncerProgress(bouncerHideAmount)), false); } private static float getAlpha(int position, float expansion) { return Interpolators.LINEAR_OUT_SLOW_IN.getInterpolation( position == POSITION_TOP ? getDreamAlphaScaledExpansion(expansion) - : getBackScrimScaledExpansion(expansion + 0.03f)); + : aboutToShowBouncerProgress(expansion + 0.03f)); } private float getTranslationY(int position, float expansion) { final float fraction = Interpolators.LINEAR_OUT_SLOW_IN.getInterpolation( position == POSITION_TOP ? getDreamYPositionScaledExpansion(expansion) - : getBackScrimScaledExpansion(expansion + 0.03f)); + : aboutToShowBouncerProgress(expansion + 0.03f)); return MathUtils.lerp(-mDreamOverlayMaxTranslationY, 0, fraction); } } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java index d4909c787d13..e878b22f61ed 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java @@ -16,8 +16,13 @@ package com.android.systemui.dreams; +import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN; +import static android.app.StatusBarManager.WINDOW_STATE_HIDING; +import static android.app.StatusBarManager.WINDOW_STATE_SHOWING; + import android.annotation.Nullable; import android.app.AlarmManager; +import android.app.StatusBarManager; import android.content.res.Resources; import android.hardware.SensorPrivacyManager; import android.net.ConnectivityManager; @@ -29,6 +34,7 @@ import android.os.UserHandle; import android.provider.Settings; import android.text.format.DateFormat; import android.util.PluralsMessageFormatter; +import android.view.View; import com.android.systemui.R; import com.android.systemui.dagger.qualifiers.Main; @@ -36,6 +42,7 @@ import com.android.systemui.dreams.dagger.DreamOverlayComponent; import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController; import com.android.systemui.statusbar.policy.NextAlarmController; import com.android.systemui.statusbar.policy.ZenModeController; +import com.android.systemui.statusbar.window.StatusBarWindowStateController; import com.android.systemui.touch.TouchInsetManager; import com.android.systemui.util.ViewController; import com.android.systemui.util.time.DateFormatUtil; @@ -119,7 +126,8 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve DateFormatUtil dateFormatUtil, IndividualSensorPrivacyController sensorPrivacyController, DreamOverlayNotificationCountProvider dreamOverlayNotificationCountProvider, - ZenModeController zenModeController) { + ZenModeController zenModeController, + StatusBarWindowStateController statusBarWindowStateController) { super(view); mResources = resources; mMainExecutor = mainExecutor; @@ -131,6 +139,10 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve mSensorPrivacyController = sensorPrivacyController; mDreamOverlayNotificationCountProvider = dreamOverlayNotificationCountProvider; mZenModeController = zenModeController; + + // Register to receive show/hide updates for the system status bar. Our custom status bar + // needs to hide when the system status bar is showing to ovoid overlapping status bars. + statusBarWindowStateController.addListener(this::onSystemStatusBarStateChanged); } @Override @@ -229,4 +241,22 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve } }); } + + private void onSystemStatusBarStateChanged(@StatusBarManager.WindowVisibleState int state) { + mMainExecutor.execute(() -> { + if (!mIsAttached) { + return; + } + + switch (state) { + case WINDOW_STATE_SHOWING: + mView.setVisibility(View.INVISIBLE); + break; + case WINDOW_STATE_HIDING: + case WINDOW_STATE_HIDDEN: + mView.setVisibility(View.VISIBLE); + break; + } + }); + } } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java index c147fde65cf7..54b9430eb445 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java @@ -42,6 +42,7 @@ import com.android.systemui.statusbar.phone.KeyguardBouncer; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.wm.shell.animation.FlingAnimationUtils; +import java.util.Optional; import javax.inject.Inject; import javax.inject.Named; @@ -77,7 +78,7 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler { private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private float mCurrentExpansion; - private final CentralSurfaces mCentralSurfaces; + private final Optional<CentralSurfaces> mCentralSurfaces; private VelocityTracker mVelocityTracker; @@ -107,7 +108,9 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler { // If the user scrolling favors a vertical direction, begin capturing // scrolls. mCapture = Math.abs(distanceY) > Math.abs(distanceX); - mBouncerInitiallyShowing = mCentralSurfaces.isBouncerShowing(); + mBouncerInitiallyShowing = mCentralSurfaces + .map(CentralSurfaces::isBouncerShowing) + .orElse(false); if (mCapture) { // Since the user is dragging the bouncer up, set scrimmed to false. @@ -129,13 +132,17 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler { return true; } + if (!mCentralSurfaces.isPresent()) { + return true; + } + // For consistency, we adopt the expansion definition found in the // PanelViewController. In this case, expansion refers to the view above the // bouncer. As that view's expansion shrinks, the bouncer appears. The bouncer // is fully hidden at full expansion (1) and fully visible when fully collapsed // (0). final float screenTravelPercentage = Math.abs(e1.getY() - e2.getY()) - / mCentralSurfaces.getDisplayHeight(); + / mCentralSurfaces.get().getDisplayHeight(); setPanelExpansion(mBouncerInitiallyShowing ? screenTravelPercentage : 1 - screenTravelPercentage); return true; @@ -171,7 +178,7 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler { public BouncerSwipeTouchHandler( DisplayMetrics displayMetrics, StatusBarKeyguardViewManager statusBarKeyguardViewManager, - CentralSurfaces centralSurfaces, + Optional<CentralSurfaces> centralSurfaces, NotificationShadeWindowController notificationShadeWindowController, ValueAnimatorCreator valueAnimatorCreator, VelocityTrackerFactory velocityTrackerFactory, @@ -195,7 +202,7 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler { @Override public void getTouchInitiationRegion(Region region) { - if (mCentralSurfaces.isBouncerShowing()) { + if (mCentralSurfaces.map(CentralSurfaces::isBouncerShowing).orElse(false)) { region.op(new Rect(0, 0, mDisplayMetrics.widthPixels, Math.round( mDisplayMetrics.heightPixels * mBouncerZoneScreenPercentage)), @@ -306,8 +313,12 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler { } protected void flingToExpansion(float velocity, float expansion) { + if (!mCentralSurfaces.isPresent()) { + return; + } + // The animation utils deal in pixel units, rather than expansion height. - final float viewHeight = mCentralSurfaces.getDisplayHeight(); + final float viewHeight = mCentralSurfaces.get().getDisplayHeight(); final float currentHeight = viewHeight * mCurrentExpansion; final float targetHeight = viewHeight * expansion; diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java index aaa4d9eefd29..c4531b573d22 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java +++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java @@ -42,10 +42,14 @@ import com.android.systemui.Dumpable; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; +import com.android.systemui.statusbar.commandline.Command; +import com.android.systemui.statusbar.commandline.CommandRegistry; import com.android.systemui.util.settings.SecureSettings; import java.io.PrintWriter; +import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.TreeMap; @@ -59,6 +63,10 @@ import javax.inject.Named; * * Flags can be set (or unset) via the following adb command: * + * adb shell cmd statusbar flag <id> <on|off|toggle|erase> + * + * Alternatively, you can change flags via a broadcast intent: + * * adb shell am broadcast -a com.android.systemui.action.SET_FLAG --ei id <id> [--ez value <0|1>] * * To restore a flag back to its default, leave the `--ez value <0|1>` off of the command. @@ -67,6 +75,7 @@ import javax.inject.Named; public class FeatureFlagsDebug implements FeatureFlags, Dumpable { private static final String TAG = "SysUIFlags"; static final String ALL_FLAGS = "all_flags"; + private static final String FLAG_COMMAND = "flag"; private final FlagManager mFlagManager; private final SecureSettings mSecureSettings; @@ -86,12 +95,15 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable { @Main Resources resources, DumpManager dumpManager, @Named(ALL_FLAGS) Map<Integer, Flag<?>> allFlags, + CommandRegistry commandRegistry, IStatusBarService barService) { mFlagManager = flagManager; mSecureSettings = secureSettings; mResources = resources; mSystemProperties = systemProperties; mAllFlags = allFlags; + mBarService = barService; + IntentFilter filter = new IntentFilter(); filter.addAction(ACTION_SET_FLAG); filter.addAction(ACTION_GET_FLAGS); @@ -100,7 +112,7 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable { context.registerReceiver(mReceiver, filter, null, null, Context.RECEIVER_EXPORTED_UNAUDITED); dumpManager.registerDumpable(TAG, this); - mBarService = barService; + commandRegistry.registerCommand(FLAG_COMMAND, FlagCommand::new); } @Override @@ -276,6 +288,31 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable { } } + private void setBooleanFlagInternal(Flag<?> flag, boolean value) { + if (flag instanceof BooleanFlag) { + setFlagValue(flag.getId(), value, BooleanFlagSerializer.INSTANCE); + } else if (flag instanceof ResourceBooleanFlag) { + setFlagValue(flag.getId(), value, BooleanFlagSerializer.INSTANCE); + } else if (flag instanceof SysPropBooleanFlag) { + // Store SysProp flags in SystemProperties where they can read by outside parties. + mSystemProperties.setBoolean(((SysPropBooleanFlag) flag).getName(), value); + dispatchListenersAndMaybeRestart(flag.getId(), + FeatureFlagsDebug.this::restartAndroid); + } else { + throw new IllegalArgumentException("Unknown flag type"); + } + } + + private void setStringFlagInternal(Flag<?> flag, String value) { + if (flag instanceof StringFlag) { + setFlagValue(flag.getId(), value, StringFlagSerializer.INSTANCE); + } else if (flag instanceof ResourceStringFlag) { + setFlagValue(flag.getId(), value, StringFlagSerializer.INSTANCE); + } else { + throw new IllegalArgumentException("Unknown flag type"); + } + } + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -327,24 +364,19 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable { } Object value = extras.get(EXTRA_VALUE); - if (flag instanceof BooleanFlag && value instanceof Boolean) { - setFlagValue(id, (Boolean) value, BooleanFlagSerializer.INSTANCE); - } else if (flag instanceof ResourceBooleanFlag && value instanceof Boolean) { - setFlagValue(id, (Boolean) value, BooleanFlagSerializer.INSTANCE); - } else if (flag instanceof SysPropBooleanFlag && value instanceof Boolean) { - // Store SysProp flags in SystemProperties where they can read by outside parties. - mSystemProperties.setBoolean( - ((SysPropBooleanFlag) flag).getName(), (Boolean) value); - dispatchListenersAndMaybeRestart(flag.getId(), - FeatureFlagsDebug.this::restartAndroid); - } else if (flag instanceof StringFlag && value instanceof String) { - setFlagValue(id, (String) value, StringFlagSerializer.INSTANCE); - } else if (flag instanceof ResourceStringFlag && value instanceof String) { - setFlagValue(id, (String) value, StringFlagSerializer.INSTANCE); - } else { + + try { + if (value instanceof Boolean) { + setBooleanFlagInternal(flag, (Boolean) value); + } else if (value instanceof String) { + setStringFlagInternal(flag, (String) value); + } else { + throw new IllegalArgumentException("Unknown value type"); + } + } catch (IllegalArgumentException e) { Log.w(TAG, - "Unable to set " + id + " of type " + flag.getClass() + " to value of type " - + (value == null ? null : value.getClass())); + "Unable to set " + flag.getId() + " of type " + flag.getClass() + + " to value of type " + (value == null ? null : value.getClass())); } } @@ -388,4 +420,153 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable { mStringFlagCache.forEach((key, value) -> pw.println(" sysui_flag_" + key + ": [length=" + value.length() + "] \"" + value + "\"")); } + + class FlagCommand implements Command { + private final List<String> mOnCommands = List.of("true", "on", "1", "enabled"); + private final List<String> mOffCommands = List.of("false", "off", "0", "disable"); + + @Override + public void execute(@NonNull PrintWriter pw, @NonNull List<String> args) { + if (args.size() == 0) { + pw.println("Error: no flag id supplied"); + help(pw); + pw.println(); + printKnownFlags(pw); + return; + } + + if (args.size() > 2) { + pw.println("Invalid number of arguments."); + help(pw); + return; + } + + int id = 0; + try { + id = Integer.parseInt(args.get(0)); + if (!mAllFlags.containsKey(id)) { + pw.println("Unknown flag id: " + id); + pw.println(); + printKnownFlags(pw); + return; + } + } catch (NumberFormatException e) { + id = flagNameToId(args.get(0)); + if (id == 0) { + pw.println("Invalid flag. Must an integer id or flag name: " + args.get(0)); + return; + } + } + Flag<?> flag = mAllFlags.get(id); + + String cmd = ""; + if (args.size() == 2) { + cmd = args.get(1).toLowerCase(); + } + + if ("erase".equals(cmd) || "reset".equals(cmd)) { + eraseFlag(flag); + return; + } + + boolean newValue = true; + if (args.size() == 1 || "toggle".equals(cmd)) { + boolean enabled = isBooleanFlagEnabled(flag); + + if (args.size() == 1) { + pw.println("Flag " + id + " is " + enabled); + return; + } + + newValue = !enabled; + } else { + newValue = mOnCommands.contains(cmd); + if (!newValue && !mOffCommands.contains(cmd)) { + pw.println("Invalid on/off argument supplied"); + help(pw); + return; + } + } + + pw.flush(); // Next command will restart sysui, so flush before we do so. + setBooleanFlagInternal(flag, newValue); + } + + @Override + public void help(PrintWriter pw) { + pw.println( + "Usage: adb shell cmd statusbar flag <id> " + + "[true|false|1|0|on|off|enable|disable|toggle|erase|reset]"); + pw.println("The id can either be a numeric integer or the corresponding field name"); + pw.println( + "If no argument is supplied after the id, the flags runtime value is output"); + } + + private boolean isBooleanFlagEnabled(Flag<?> flag) { + if (flag instanceof BooleanFlag) { + return isEnabled((BooleanFlag) flag); + } else if (flag instanceof ResourceBooleanFlag) { + return isEnabled((ResourceBooleanFlag) flag); + } else if (flag instanceof SysPropFlag) { + return isEnabled((SysPropBooleanFlag) flag); + } + + return false; + } + + private int flagNameToId(String flagName) { + List<Field> fields = Flags.getFlagFields(); + for (Field field : fields) { + if (flagName.equals(field.getName())) { + return fieldToId(field); + } + } + + return 0; + } + + private int fieldToId(Field field) { + try { + Flag<?> flag = (Flag<?>) field.get(null); + return flag.getId(); + } catch (IllegalAccessException e) { + // no-op + } + + return 0; + } + + private void printKnownFlags(PrintWriter pw) { + List<Field> fields = Flags.getFlagFields(); + + int longestFieldName = 0; + for (Field field : fields) { + longestFieldName = Math.max(longestFieldName, field.getName().length()); + } + + pw.println("Known Flags:"); + pw.print("Flag Name"); + for (int i = 0; i < longestFieldName - "Flag Name".length() + 1; i++) { + pw.print(" "); + } + pw.println("ID Enabled?"); + for (int i = 0; i < longestFieldName; i++) { + pw.print("="); + } + pw.println(" ==== ========"); + for (Field field : fields) { + int id = fieldToId(field); + if (id == 0 || !mAllFlags.containsKey(id)) { + continue; + } + pw.print(field.getName()); + int fieldWidth = field.getName().length(); + for (int i = 0; i < longestFieldName - fieldWidth + 1; i++) { + pw.print(" "); + } + pw.printf("%-4d ", id); + pw.println(isBooleanFlagEnabled(mAllFlags.get(id))); + } + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java index 0819f308c94d..afa7d5e0a9c4 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java @@ -20,7 +20,9 @@ import com.android.internal.annotations.Keep; import com.android.systemui.R; import java.lang.reflect.Field; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -149,7 +151,7 @@ public class Flags { /***************************************/ // 900 - media public static final BooleanFlag MEDIA_TAP_TO_TRANSFER = new BooleanFlag(900, true); - public static final BooleanFlag MEDIA_SESSION_ACTIONS = new BooleanFlag(901, true); + public static final BooleanFlag MEDIA_SESSION_ACTIONS = new BooleanFlag(901, false); public static final BooleanFlag MEDIA_NEARBY_DEVICES = new BooleanFlag(903, true); public static final BooleanFlag MEDIA_MUTE_AWAIT = new BooleanFlag(904, true); @@ -182,25 +184,36 @@ public class Flags { if (sFlagMap != null) { return sFlagMap; } + Map<Integer, Flag<?>> flags = new HashMap<>(); + List<Field> flagFields = getFlagFields(); + + for (Field field : flagFields) { + try { + Flag<?> flag = (Flag<?>) field.get(null); + flags.put(flag.getId(), flag); + } catch (IllegalAccessException e) { + // no-op + } + } + sFlagMap = flags; + + return sFlagMap; + } + + static List<Field> getFlagFields() { Field[] fields = Flags.class.getFields(); + List<Field> result = new ArrayList<>(); for (Field field : fields) { Class<?> t = field.getType(); if (Flag.class.isAssignableFrom(t)) { - try { - Flag<?> flag = (Flag<?>) field.get(null); - flags.put(flag.getId(), flag); - } catch (IllegalAccessException e) { - // no-op - } + result.add(field); } } - sFlagMap = flags; - - return sFlagMap; + return result; } // | . . . . . . . . . . . . . . . . . . . | // | | diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt index 35f29b94966f..a8c286241141 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt @@ -23,6 +23,7 @@ import android.content.Context import android.graphics.Matrix import android.graphics.Rect import android.os.Handler +import android.provider.Settings import android.util.Log import android.view.RemoteAnimationTarget import android.view.SyncRtSurfaceTransactionApplier @@ -94,6 +95,20 @@ const val DISMISS_AMOUNT_EXIT_KEYGUARD_THRESHOLD = 0.4f const val UNLOCK_ANIMATION_DURATION_MS = 200L /** + * How long the in-window launcher icon animation takes. This is used if the launcher is underneath + * the lock screen and supports in-window animations. + * + * This animation will take place entirely within the Launcher window. We can safely unlock the + * device, end remote animations, etc. even if this is still running. + */ +const val LAUNCHER_ICONS_ANIMATION_DURATION_MS = 633L + +/** + * How long to wait for the shade to get out of the way before starting the canned unlock animation. + */ +const val CANNED_UNLOCK_START_DELAY = 100L + +/** * Duration for the alpha animation on the surface behind. This plays to fade in the surface during * a swipe to unlock (and to fade it back out if the swipe is cancelled). */ @@ -119,7 +134,7 @@ const val UNLOCK_ANIMATION_SURFACE_BEHIND_START_DELAY_MS = 75L */ @SysUISingleton class KeyguardUnlockAnimationController @Inject constructor( - context: Context, + private val context: Context, private val keyguardStateController: KeyguardStateController, private val keyguardViewMediator: Lazy<KeyguardViewMediator>, @@ -374,6 +389,10 @@ class KeyguardUnlockAnimationController @Inject constructor( listeners.add(listener) } + fun removeKeyguardUnlockAnimationListener(listener: KeyguardUnlockAnimationListener) { + listeners.remove(listener) + } + /** * Called from [KeyguardViewMediator] to tell us that the RemoteAnimation on the surface behind * the keyguard has started successfully. We can use these parameters to directly manipulate the @@ -483,23 +502,34 @@ class KeyguardUnlockAnimationController @Inject constructor( * transition if possible. */ private fun unlockToLauncherWithInWindowAnimations() { - unlockingToLauncherWithInWindowAnimations = true - // See if we can do the smartspace transition, and if so, do it! if (prepareForSmartspaceTransition()) { animateSmartspaceToDestination() listeners.forEach { it.onSmartspaceSharedElementTransitionStarted() } } - // Tell the launcher to prepare for the animation by setting its views invisible and - // syncing the selected smartspace pages. - launcherUnlockController?.prepareForUnlock( - unlockingWithSmartspaceTransition /* willAnimateSmartspace */, - (lockscreenSmartspace as BcSmartspaceDataPlugin.SmartspaceView?)?.selectedPage ?: -1) + val startDelay = Settings.Secure.getLong( + context.contentResolver, "unlock_start_delay", CANNED_UNLOCK_START_DELAY) + val duration = Settings.Secure.getLong( + context.contentResolver, "unlock_duration", LAUNCHER_ICONS_ANIMATION_DURATION_MS) - // Begin the animation. + unlockingToLauncherWithInWindowAnimations = true + prepareLauncherWorkspaceForUnlockAnimation() + + // Begin the animation, waiting for the shade to animate out. launcherUnlockController?.playUnlockAnimation( - true /* unlocked */, UNLOCK_ANIMATION_DURATION_MS) + true /* unlocked */, + duration /* duration */, + startDelay /* startDelay */) + + handler.postDelayed({ + applyParamsToSurface( + SyncRtSurfaceTransactionApplier.SurfaceParams.Builder( + surfaceBehindRemoteAnimationTarget!!.leash) + .withAlpha(1f) + .build()) + }, startDelay) + if (!unlockingWithSmartspaceTransition) { // If we are not unlocking with the smartspace transition, wait for the unlock animation // to end and then finish the remote animation. If we are using the smartspace @@ -509,9 +539,18 @@ class KeyguardUnlockAnimationController @Inject constructor( false /* cancelled */) }, UNLOCK_ANIMATION_DURATION_MS) } + } - // Wait a moment, then show the launcher surface. - setSurfaceBehindAppearAmount(1f) + /** + * Asks Launcher to prepare the workspace to be unlocked. This sets up the animation and makes + * the page invisible. + */ + private fun prepareLauncherWorkspaceForUnlockAnimation() { + // Tell the launcher to prepare for the animation by setting its views invisible and + // syncing the selected smartspace pages. + launcherUnlockController?.prepareForUnlock( + unlockingWithSmartspaceTransition /* willAnimateSmartspace */, + (lockscreenSmartspace as BcSmartspaceDataPlugin.SmartspaceView?)?.selectedPage ?: -1) } /** @@ -615,20 +654,18 @@ class KeyguardUnlockAnimationController @Inject constructor( } if (unlockingToLauncherWithInWindowAnimations) { - // If we're using the in-window launcher animations, and haven't yet applied alpha = 1f - // to the launcher surface, do that now so we can see the launcher animations. - if (surfaceBehindParams?.alpha?.let { it < 1f } != false) { - applyParamsToSurface( - SyncRtSurfaceTransactionApplier.SurfaceParams.Builder( - surfaceBehindRemoteAnimationTarget!!.leash) - .withAlpha(1f) - .build()) - } - // If we aren't using the canned unlock animation (which would be setting the unlock // amount in its update listener), do it here. if (!isPlayingCannedUnlockAnimation()) { launcherUnlockController?.setUnlockAmount(amount) + + if (surfaceBehindParams?.alpha?.let { it < 1f } != false) { + applyParamsToSurface( + SyncRtSurfaceTransactionApplier.SurfaceParams.Builder( + surfaceBehindRemoteAnimationTarget!!.leash) + .withAlpha(1f) + .build()) + } } } else { // Otherwise, animate in the surface's scale/transltion. @@ -743,9 +780,10 @@ class KeyguardUnlockAnimationController @Inject constructor( !keyguardViewMediator.get().requestedShowSurfaceBehindKeyguard()) { // We passed the threshold, and we're not yet showing the surface behind the // keyguard. Animate it in. - if (canPerformInWindowLauncherAnimations()) { - launcherUnlockController?.setUnlockAmount(0f) + if (!unlockingToLauncherWithInWindowAnimations && + canPerformInWindowLauncherAnimations()) { unlockingToLauncherWithInWindowAnimations = true + prepareLauncherWorkspaceForUnlockAnimation() } keyguardViewMediator.get().showSurfaceBehindKeyguard() fadeInSurfaceBehind() @@ -928,7 +966,11 @@ class KeyguardUnlockAnimationController @Inject constructor( * the device. */ fun canPerformInWindowLauncherAnimations(): Boolean { - return isNexusLauncherUnderneath() && launcherUnlockController != null + return isNexusLauncherUnderneath() && + launcherUnlockController != null && + // Temporarily disable for foldables since foldable launcher has two first pages, + // which breaks the in-window animation. + !isFoldable(context) } /** @@ -969,5 +1011,9 @@ class KeyguardUnlockAnimationController @Inject constructor( .runningTask?.topActivity?.className?.equals( QuickStepContract.LAUNCHER_ACTIVITY_CLASS_NAME) ?: false } + + fun isFoldable(context: Context): Boolean { + return context.resources.getIntArray(R.array.config_foldedDeviceStates).isNotEmpty() + } } }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java index 71dfa7433c32..165af135a792 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java @@ -25,6 +25,7 @@ import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardDisplayManager; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardViewController; +import com.android.keyguard.ViewMediatorCallback; import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent; import com.android.keyguard.dagger.KeyguardStatusBarViewComponent; import com.android.keyguard.dagger.KeyguardStatusViewComponent; @@ -127,4 +128,10 @@ public class KeyguardModule { notificationShadeWindowController, activityLaunchAnimator); } + + /** */ + @Provides + public ViewMediatorCallback providesViewMediatorCallback(KeyguardViewMediator viewMediator) { + return viewMediator.getViewMediatorCallback(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt index 6d589aac2079..e16da89d6ec8 100644 --- a/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt +++ b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt @@ -23,6 +23,9 @@ import java.io.PrintWriter import java.text.SimpleDateFormat import java.util.ArrayDeque import java.util.Locale +import java.util.concurrent.ArrayBlockingQueue +import java.util.concurrent.BlockingQueue +import kotlin.concurrent.thread /** * A simple ring buffer of recyclable log messages @@ -81,6 +84,22 @@ class LogBuffer @JvmOverloads constructor( } private val buffer: ArrayDeque<LogMessageImpl> = ArrayDeque() + private val echoMessageQueue: BlockingQueue<LogMessageImpl>? = + if (logcatEchoTracker.logInBackgroundThread) ArrayBlockingQueue(poolSize) else null + + init { + if (logcatEchoTracker.logInBackgroundThread && echoMessageQueue != null) { + thread(start = true, priority = Thread.NORM_PRIORITY) { + try { + while (true) { + echoToDesiredEndpoints(echoMessageQueue.take()) + } + } catch (e: InterruptedException) { + Thread.currentThread().interrupt() + } + } + } + } var frozen = false private set @@ -176,6 +195,22 @@ class LogBuffer @JvmOverloads constructor( buffer.removeFirst() } buffer.add(message as LogMessageImpl) + // Log in the background thread only if echoMessageQueue exists and has capacity (checking + // capacity avoids the possibility of blocking this thread) + if (echoMessageQueue != null && echoMessageQueue.remainingCapacity() > 0) { + try { + echoMessageQueue.put(message) + } catch (e: InterruptedException) { + // the background thread has been shut down, so just log on this one + echoToDesiredEndpoints(message) + } + } else { + echoToDesiredEndpoints(message) + } + } + + /** Sends message to echo after determining whether to use Logcat and/or systrace. */ + private fun echoToDesiredEndpoints(message: LogMessageImpl) { val includeInLogcat = logcatEchoTracker.isBufferLoggable(name, message.level) || logcatEchoTracker.isTagLoggable(message.tag, message.level) echo(message, toLogcat = includeInLogcat, toSystrace = systrace) diff --git a/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt index 3022f4b42a42..8cda4236bc87 100644 --- a/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt +++ b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt @@ -29,4 +29,9 @@ interface LogcatEchoTracker { * Whether [tagName] should echo messages of [level] or higher to logcat. */ fun isTagLoggable(tagName: String, level: LogLevel): Boolean + + /** + * Whether to log messages in a background thread. + */ + val logInBackgroundThread: Boolean } diff --git a/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt index 23942e1d6e3c..91734cc361b0 100644 --- a/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt +++ b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt @@ -41,6 +41,7 @@ class LogcatEchoTrackerDebug private constructor( ) : LogcatEchoTracker { private val cachedBufferLevels: MutableMap<String, LogLevel> = mutableMapOf() private val cachedTagLevels: MutableMap<String, LogLevel> = mutableMapOf() + override val logInBackgroundThread = true companion object Factory { @JvmStatic diff --git a/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt index 394f624a3e58..1a4ad1907ff1 100644 --- a/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt +++ b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt @@ -20,6 +20,8 @@ package com.android.systemui.log * Production version of [LogcatEchoTracker] that isn't configurable. */ class LogcatEchoTrackerProd : LogcatEchoTracker { + override val logInBackgroundThread = false + override fun isBufferLoggable(bufferName: String, level: LogLevel): Boolean { return level >= LogLevel.WARNING } diff --git a/packages/SystemUI/src/com/android/systemui/media/AnimationBindHandler.kt b/packages/SystemUI/src/com/android/systemui/media/AnimationBindHandler.kt new file mode 100644 index 000000000000..013683e962a4 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/AnimationBindHandler.kt @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media + +import android.graphics.drawable.Animatable2 +import android.graphics.drawable.Drawable + +/** + * AnimationBindHandler is responsible for tracking the bound animation state and preventing + * jank and conflicts due to media notifications arriving at any time during an animation. It + * does this in two parts. + * - Exit animations fired as a result of user input are tracked. When these are running, any + * bind actions are delayed until the animation completes (and then fired in sequence). + * - Continuous animations are tracked using their rebind id. Later calls using the same + * rebind id will be totally ignored to prevent the continuous animation from restarting. + */ +internal class AnimationBindHandler : Animatable2.AnimationCallback() { + private val onAnimationsComplete = mutableListOf<() -> Unit>() + private val registrations = mutableListOf<Animatable2>() + private var rebindId: Int? = null + + val isAnimationRunning: Boolean + get() = registrations.any { it.isRunning } + + /** + * This check prevents rebinding to the action button if the identifier has not changed. A + * null value is always considered to be changed. This is used to prevent the connecting + * animation from rebinding (and restarting) if multiple buffer PlaybackStates are pushed by + * an application in a row. + */ + fun updateRebindId(newRebindId: Int?): Boolean { + if (rebindId == null || newRebindId == null || rebindId != newRebindId) { + rebindId = newRebindId + return true + } + return false + } + + fun tryRegister(drawable: Drawable?) { + if (drawable is Animatable2) { + val anim = drawable as Animatable2 + anim.registerAnimationCallback(this) + registrations.add(anim) + } + } + + fun unregisterAll() { + registrations.forEach { it.unregisterAnimationCallback(this) } + registrations.clear() + } + + fun tryExecute(action: () -> Unit) { + if (isAnimationRunning) { + onAnimationsComplete.add(action) + } else { + action() + } + } + + override fun onAnimationEnd(drawable: Drawable) { + super.onAnimationEnd(drawable) + if (!isAnimationRunning) { + onAnimationsComplete.forEach { it() } + onAnimationsComplete.clear() + } + } +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/media/ColorSchemeTransition.kt b/packages/SystemUI/src/com/android/systemui/media/ColorSchemeTransition.kt new file mode 100644 index 000000000000..2ae1806f3b3d --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/ColorSchemeTransition.kt @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media + +import android.animation.ArgbEvaluator +import android.animation.ValueAnimator.AnimatorUpdateListener +import android.animation.ValueAnimator +import android.content.Context +import android.content.res.ColorStateList +import com.android.internal.R +import com.android.internal.annotations.VisibleForTesting +import com.android.settingslib.Utils +import com.android.systemui.monet.ColorScheme + +/** + * ColorTransition is responsible for managing the animation between two specific colors. + * It uses a ValueAnimator to execute the animation and interpolate between the source color and + * the target color. + * + * Selection of the target color from the scheme, and application of the interpolated color + * are delegated to callbacks. + */ +open class ColorTransition( + private val defaultColor: Int, + private val extractColor: (ColorScheme) -> Int, + private val applyColor: (Int) -> Unit +) : AnimatorUpdateListener { + + private val argbEvaluator = ArgbEvaluator() + private val valueAnimator = buildAnimator() + var sourceColor: Int = defaultColor + var currentColor: Int = defaultColor + var targetColor: Int = defaultColor + + override fun onAnimationUpdate(animation: ValueAnimator) { + currentColor = argbEvaluator.evaluate( + animation.animatedFraction, sourceColor, targetColor + ) as Int + applyColor(currentColor) + } + + fun updateColorScheme(scheme: ColorScheme?) { + val newTargetColor = if (scheme == null) defaultColor else extractColor(scheme) + if (newTargetColor != targetColor) { + sourceColor = currentColor + targetColor = newTargetColor + valueAnimator.cancel() + valueAnimator.start() + } + } + + init { + applyColor(defaultColor) + } + + @VisibleForTesting + open fun buildAnimator(): ValueAnimator { + val animator = ValueAnimator.ofFloat(0f, 1f) + animator.duration = 333 + animator.addUpdateListener(this) + return animator + } +} + +typealias ColorTransitionFactory = (Int, (ColorScheme) -> Int, (Int) -> Unit) -> ColorTransition + +/** + * ColorSchemeTransition constructs a ColorTransition for each color in the scheme + * that needs to be transitioned when changed. It also sets up the assignment functions for sending + * the sending the interpolated colors to the appropriate views. + */ +class ColorSchemeTransition internal constructor( + private val context: Context, + mediaViewHolder: MediaViewHolder, + colorTransitionFactory: ColorTransitionFactory +) { + constructor(context: Context, mediaViewHolder: MediaViewHolder) : + this(context, mediaViewHolder, ::ColorTransition) + + val bgColor = context.getColor(com.android.systemui.R.color.material_dynamic_secondary95) + + val surfaceColor = colorTransitionFactory( + bgColor, + { colorScheme -> colorScheme.accent2[9] }, // A2-800 + { surfaceColor -> + val colorList = ColorStateList.valueOf(surfaceColor) + mediaViewHolder.player.backgroundTintList = colorList + mediaViewHolder.albumView.foregroundTintList = colorList + mediaViewHolder.albumView.backgroundTintList = colorList + mediaViewHolder.seamlessIcon.imageTintList = colorList + mediaViewHolder.seamlessText.setTextColor(surfaceColor) + mediaViewHolder.dismissText.setTextColor(surfaceColor) + }) + + val accentPrimary = colorTransitionFactory( + loadDefaultColor(R.attr.textColorPrimary), + { colorScheme -> colorScheme.accent1[2] }, // A1-100 + { accentPrimary -> + val accentColorList = ColorStateList.valueOf(accentPrimary) + mediaViewHolder.actionPlayPause.backgroundTintList = accentColorList + mediaViewHolder.seamlessButton.backgroundTintList = accentColorList + mediaViewHolder.settings.imageTintList = accentColorList + mediaViewHolder.cancelText.backgroundTintList = accentColorList + mediaViewHolder.dismissText.backgroundTintList = accentColorList + }) + + val textPrimary = colorTransitionFactory( + loadDefaultColor(R.attr.textColorPrimary), + { colorScheme -> colorScheme.neutral1[1] }, // N1-50 + { textPrimary -> + mediaViewHolder.titleText.setTextColor(textPrimary) + val textColorList = ColorStateList.valueOf(textPrimary) + mediaViewHolder.seekBar.thumb.setTintList(textColorList) + mediaViewHolder.seekBar.progressTintList = textColorList + mediaViewHolder.longPressText.setTextColor(textColorList) + mediaViewHolder.cancelText.setTextColor(textColorList) + mediaViewHolder.scrubbingElapsedTimeView.setTextColor(textColorList) + mediaViewHolder.scrubbingTotalTimeView.setTextColor(textColorList) + for (button in mediaViewHolder.getTransparentActionButtons()) { + button.imageTintList = textColorList + } + }) + + val textPrimaryInverse = colorTransitionFactory( + loadDefaultColor(R.attr.textColorPrimaryInverse), + { colorScheme -> colorScheme.neutral1[10] }, // N1-900 + { textPrimaryInverse -> + mediaViewHolder.actionPlayPause.imageTintList = + ColorStateList.valueOf(textPrimaryInverse) + }) + + val textSecondary = colorTransitionFactory( + loadDefaultColor(R.attr.textColorSecondary), + { colorScheme -> colorScheme.neutral2[3] }, // N2-200 + { textSecondary -> mediaViewHolder.artistText.setTextColor(textSecondary) }) + + val textTertiary = colorTransitionFactory( + loadDefaultColor(R.attr.textColorTertiary), + { colorScheme -> colorScheme.neutral2[5] }, // N2-400 + { textTertiary -> + mediaViewHolder.seekBar.progressBackgroundTintList = + ColorStateList.valueOf(textTertiary) + }) + + val colorTransitions = arrayOf( + surfaceColor, accentPrimary, textPrimary, + textPrimaryInverse, textSecondary, textTertiary) + + private fun loadDefaultColor(id: Int): Int { + return Utils.getColorAttr(context, id).defaultColor + } + + fun updateColorScheme(colorScheme: ColorScheme?) { + colorTransitions.forEach { it.updateColorScheme(colorScheme) } + } +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt index a636dc5e6ae1..ca25a18503ec 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt @@ -127,7 +127,6 @@ class MediaCarouselController @Inject constructor( private val visualStabilityCallback: OnReorderingAllowedListener private var needsReordering: Boolean = false private var keysNeedRemoval = mutableSetOf<String>() - private var bgColor = getBackgroundColor() protected var shouldScrollToActivePlayer: Boolean = false private var isRtl: Boolean = false set(value) { @@ -488,7 +487,7 @@ class MediaCarouselController @Inject constructor( val lp = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) newRecs.recommendationViewHolder?.recommendations?.setLayoutParams(lp) - newRecs.bindRecommendation(data.copy(backgroundColor = bgColor)) + newRecs.bindRecommendation(data) val curVisibleMediaKey = MediaPlayerData.playerKeys() .elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex) MediaPlayerData.addMediaRecommendation(key, data, newRecs, shouldPrioritize, systemClock) @@ -508,6 +507,11 @@ class MediaCarouselController @Inject constructor( dismissMediaData: Boolean = true, dismissRecommendation: Boolean = true ) { + if (key == MediaPlayerData.smartspaceMediaKey()) { + MediaPlayerData.smartspaceMediaData?.let { + logger.logRecommendationRemoved(it.packageName, it.instanceId) + } + } val removed = MediaPlayerData.removeMediaPlayer(key) removed?.apply { mediaCarouselScrollHandler.onPrePlayerRemoved(removed) @@ -529,7 +533,6 @@ class MediaCarouselController @Inject constructor( } private fun recreatePlayers() { - bgColor = getBackgroundColor() pageIndicator.tintList = ColorStateList.valueOf(R.color.material_dynamic_neutral_variant80) MediaPlayerData.mediaData().forEach { (key, data, isSsMediaRec) -> @@ -549,10 +552,6 @@ class MediaCarouselController @Inject constructor( } } - private fun getBackgroundColor(): Int { - return context.getColor(R.color.material_dynamic_secondary95) - } - private fun updatePageIndicator() { val numPages = mediaContent.getChildCount() pageIndicator.setNumPages(numPages) @@ -899,7 +898,6 @@ internal object MediaPlayerData { private val EMPTY = MediaData( userId = -1, initialized = false, - backgroundColor = 0, app = null, appIcon = null, artist = null, diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java index 8ddec5c7d9f7..48a63ed0a2d6 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java @@ -18,6 +18,9 @@ package com.android.systemui.media; import static android.provider.Settings.ACTION_MEDIA_CONTROLS_SETTINGS; +import android.animation.Animator; +import android.animation.AnimatorInflater; +import android.animation.AnimatorSet; import android.app.PendingIntent; import android.app.WallpaperColors; import android.app.smartspace.SmartspaceAction; @@ -31,20 +34,22 @@ import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; import android.graphics.Rect; import android.graphics.drawable.Animatable; -import android.graphics.drawable.Animatable2; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; +import android.graphics.drawable.TransitionDrawable; import android.media.session.MediaController; import android.media.session.MediaSession; import android.media.session.PlaybackState; import android.os.Process; import android.text.TextUtils; import android.util.Log; +import android.util.Pair; import android.view.View; import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.view.animation.Interpolator; import android.widget.ImageButton; import android.widget.ImageView; -import android.widget.SeekBar; import android.widget.TextView; import androidx.annotation.NonNull; @@ -52,12 +57,16 @@ import androidx.annotation.Nullable; import androidx.annotation.UiThread; import androidx.constraintlayout.widget.ConstraintSet; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.logging.InstanceId; +import com.android.settingslib.Utils; import com.android.settingslib.widget.AdaptiveIcon; +import com.android.systemui.ActivityIntentHelper; import com.android.systemui.R; import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.animation.GhostedViewLaunchAnimatorController; +import com.android.systemui.animation.Interpolators; import com.android.systemui.broadcast.BroadcastSender; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; @@ -66,6 +75,8 @@ import com.android.systemui.monet.ColorScheme; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.shared.system.SysUiStatsLog; +import com.android.systemui.statusbar.NotificationLockscreenUserManager; +import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.animation.TransitionLayout; import com.android.systemui.util.time.SystemClock; @@ -90,8 +101,7 @@ public class MediaControlPanel { + ".android.apps.gsa.staticplugins.opa.smartspace.ExportedSmartspaceTrampolineActivity"; private static final String EXTRAS_SMARTSPACE_INTENT = "com.google.android.apps.gsa.smartspace.extra.SMARTSPACE_INTENT"; - private static final int MEDIA_RECOMMENDATION_ITEMS_PER_ROW = 3; - private static final int MEDIA_RECOMMENDATION_MAX_NUM = 6; + private static final int MEDIA_RECOMMENDATION_MAX_NUM = 3; private static final String KEY_SMARTSPACE_ARTIST_NAME = "artist_name"; private static final String KEY_SMARTSPACE_OPEN_IN_FOREGROUND = "KEY_OPEN_IN_FOREGROUND"; private static final String KEY_SMARTSPACE_APP_NAME = "KEY_SMARTSPACE_APP_NAME"; @@ -141,13 +151,21 @@ public class MediaControlPanel { private MediaSession.Token mToken; private MediaController mController; private Lazy<MediaDataManager> mMediaDataManagerLazy; - private int mBackgroundColor; // Uid for the media app. protected int mUid = Process.INVALID_UID; private int mSmartspaceMediaItemsCount; private MediaCarouselController mMediaCarouselController; private final MediaOutputDialogFactory mMediaOutputDialogFactory; private final FalsingManager mFalsingManager; + private MetadataAnimationHandler mMetadataAnimationHandler; + private ColorSchemeTransition mColorSchemeTransition; + private Drawable mPrevArtwork = null; + private int mArtworkBoundId = 0; + private int mArtworkNextBindRequestId = 0; + + private final KeyguardStateController mKeyguardStateController; + private final ActivityIntentHelper mActivityIntentHelper; + private final NotificationLockscreenUserManager mLockscreenUserManager; // Used for logging. protected boolean mIsImpressed = false; @@ -171,15 +189,23 @@ public class MediaControlPanel { * @param activityStarter activity starter */ @Inject - public MediaControlPanel(Context context, + public MediaControlPanel( + Context context, @Background Executor backgroundExecutor, @Main Executor mainExecutor, - ActivityStarter activityStarter, BroadcastSender broadcastSender, - MediaViewController mediaViewController, SeekBarViewModel seekBarViewModel, + ActivityStarter activityStarter, + BroadcastSender broadcastSender, + MediaViewController mediaViewController, + SeekBarViewModel seekBarViewModel, Lazy<MediaDataManager> lazyMediaDataManager, MediaOutputDialogFactory mediaOutputDialogFactory, MediaCarouselController mediaCarouselController, - FalsingManager falsingManager, SystemClock systemClock, MediaUiEventLogger logger) { + FalsingManager falsingManager, + SystemClock systemClock, + MediaUiEventLogger logger, + KeyguardStateController keyguardStateController, + ActivityIntentHelper activityIntentHelper, + NotificationLockscreenUserManager lockscreenUserManager) { mContext = context; mBackgroundExecutor = backgroundExecutor; mMainExecutor = mainExecutor; @@ -193,6 +219,9 @@ public class MediaControlPanel { mFalsingManager = falsingManager; mSystemClock = systemClock; mLogger = logger; + mKeyguardStateController = keyguardStateController; + mActivityIntentHelper = activityIntentHelper; + mLockscreenUserManager = lockscreenUserManager; mSeekBarViewModel.setLogSeek(() -> { if (mPackageName != null && mInstanceId != null) { @@ -306,6 +335,32 @@ public class MediaControlPanel { mActivityStarter.startActivity(SETTINGS_INTENT, true /* dismissShade */); } }); + + TextView titleText = mMediaViewHolder.getTitleText(); + TextView artistText = mMediaViewHolder.getArtistText(); + AnimatorSet enter = loadAnimator(R.anim.media_metadata_enter, + Interpolators.EMPHASIZED_DECELERATE, titleText, artistText); + AnimatorSet exit = loadAnimator(R.anim.media_metadata_exit, + Interpolators.EMPHASIZED_ACCELERATE, titleText, artistText); + + mColorSchemeTransition = new ColorSchemeTransition(mContext, mMediaViewHolder); + mMetadataAnimationHandler = new MetadataAnimationHandler(exit, enter); + } + + @VisibleForTesting + protected AnimatorSet loadAnimator(int animId, Interpolator motionInterpolator, + View... targets) { + ArrayList<Animator> animators = new ArrayList<>(); + for (View target : targets) { + AnimatorSet animator = (AnimatorSet) AnimatorInflater.loadAnimator(mContext, animId); + animator.getChildAnimations().get(0).setInterpolator(motionInterpolator); + animator.setTarget(target); + animators.add(animator); + } + + AnimatorSet result = new AnimatorSet(); + result.playTogether(animators); + return result; } /** Attaches the recommendations to the recommendation view holder. */ @@ -331,6 +386,7 @@ public class MediaControlPanel { }); mRecommendationViewHolder.getSettings().setOnClickListener(v -> { if (!mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { + mLogger.logLongPressSettings(mUid, mPackageName, mInstanceId); mActivityStarter.startActivity(SETTINGS_INTENT, true /* dismissShade */); } }); @@ -352,7 +408,6 @@ public class MediaControlPanel { } mInstanceId = data.getInstanceId(); - mBackgroundColor = data.getBackgroundColor(); if (mToken == null || !mToken.equals(token)) { mToken = token; } @@ -371,25 +426,24 @@ public class MediaControlPanel { if (mMediaViewController.isGutsVisible()) return; mLogger.logTapContentView(mUid, mPackageName, mInstanceId); logSmartspaceCardReported(SMARTSPACE_CARD_CLICK_EVENT); - mActivityStarter.postStartActivityDismissingKeyguard(clickIntent, - buildLaunchAnimatorController(mMediaViewHolder.getPlayer())); + + // See StatusBarNotificationActivityStarter#onNotificationClicked + boolean showOverLockscreen = mKeyguardStateController.isShowing() + && mActivityIntentHelper.wouldShowOverLockscreen(clickIntent.getIntent(), + mLockscreenUserManager.getCurrentUserId()); + + if (showOverLockscreen) { + mActivityStarter.startActivity(clickIntent.getIntent(), + /* dismissShade */ true, + /* animationController */ null, + /* showOverLockscreenWhenLocked */ true); + } else { + mActivityStarter.postStartActivityDismissingKeyguard(clickIntent, + buildLaunchAnimatorController(mMediaViewHolder.getPlayer())); + } }); } - // Accessibility label - mMediaViewHolder.getPlayer().setContentDescription( - mContext.getString( - R.string.controls_media_playing_item_description, - data.getSong(), data.getArtist(), data.getApp())); - - // Song name - TextView titleText = mMediaViewHolder.getTitleText(); - titleText.setText(data.getSong()); - - // Artist name - TextView artistText = mMediaViewHolder.getArtistText(); - artistText.setText(data.getArtist()); - // Seek Bar final MediaController controller = getController(); mBackgroundExecutor.execute(() -> mSeekBarViewModel.updateController(controller)); @@ -398,11 +452,16 @@ public class MediaControlPanel { bindLongPressMenu(data); bindActionButtons(data); bindScrubbingTime(data); - bindArtworkAndColors(data); + + boolean isSongUpdated = bindSongMetadata(data); + bindArtworkAndColors(data, isSongUpdated); // TODO: We don't need to refresh this state constantly, only if the state actually changed // to something which might impact the measurement - mMediaViewController.refreshState(); + // State refresh interferes with the translation animation, only run it if it's not running. + if (!mMetadataAnimationHandler.isRunning()) { + mMediaViewController.refreshState(); + } } private void bindOutputSwitcherChip(MediaData data) { @@ -424,7 +483,7 @@ public class MediaControlPanel { Drawable icon = device.getIcon(); if (icon instanceof AdaptiveIcon) { AdaptiveIcon aIcon = (AdaptiveIcon) icon; - aIcon.setBackgroundColor(mBackgroundColor); + aIcon.setBackgroundColor(mColorSchemeTransition.getBgColor()); iconView.setImageDrawable(aIcon); } else { iconView.setImageDrawable(icon); @@ -493,120 +552,135 @@ public class MediaControlPanel { }); } - private void bindArtworkAndColors(MediaData data) { - // Default colors - int surfaceColor = mBackgroundColor; - int accentPrimary = com.android.settingslib.Utils.getColorAttr(mContext, - com.android.internal.R.attr.textColorPrimary).getDefaultColor(); - int textPrimary = com.android.settingslib.Utils.getColorAttr(mContext, - com.android.internal.R.attr.textColorPrimary).getDefaultColor(); - int textPrimaryInverse = com.android.settingslib.Utils.getColorAttr(mContext, - com.android.internal.R.attr.textColorPrimaryInverse).getDefaultColor(); - int textSecondary = com.android.settingslib.Utils.getColorAttr(mContext, - com.android.internal.R.attr.textColorSecondary).getDefaultColor(); - int textTertiary = com.android.settingslib.Utils.getColorAttr(mContext, - com.android.internal.R.attr.textColorTertiary).getDefaultColor(); - - // Album art - ColorScheme colorScheme = null; - ImageView albumView = mMediaViewHolder.getAlbumView(); - boolean hasArtwork = data.getArtwork() != null; - if (hasArtwork) { - colorScheme = new ColorScheme(WallpaperColors.fromBitmap(data.getArtwork().getBitmap()), - true); - - // Scale artwork to fit background - int width = mMediaViewHolder.getPlayer().getWidth(); - int height = mMediaViewHolder.getPlayer().getHeight(); - Drawable artwork = getScaledBackground(data.getArtwork(), width, height); - albumView.setPadding(0, 0, 0, 0); - albumView.setImageDrawable(artwork); - albumView.setClipToOutline(true); - } else { - // If there's no artwork, use colors from the app icon - try { - Drawable icon = mContext.getPackageManager().getApplicationIcon( - data.getPackageName()); - colorScheme = new ColorScheme(WallpaperColors.fromDrawable(icon), true); - } catch (PackageManager.NameNotFoundException e) { - Log.w(TAG, "Cannot find icon for package " + data.getPackageName(), e); - } - } + private boolean bindSongMetadata(MediaData data) { + // Accessibility label + mMediaViewHolder.getPlayer().setContentDescription( + mContext.getString( + R.string.controls_media_playing_item_description, + data.getSong(), data.getArtist(), data.getApp())); - // Get colors for player - if (colorScheme != null) { - surfaceColor = colorScheme.getAccent2().get(9); // A2-800 - accentPrimary = colorScheme.getAccent1().get(2); // A1-100 - textPrimary = colorScheme.getNeutral1().get(1); // N1-50 - textPrimaryInverse = colorScheme.getNeutral1().get(10); // N1-900 - textSecondary = colorScheme.getNeutral2().get(3); // N2-200 - textTertiary = colorScheme.getNeutral2().get(5); // N2-400 - } + TextView titleText = mMediaViewHolder.getTitleText(); + TextView artistText = mMediaViewHolder.getArtistText(); + return mMetadataAnimationHandler.setNext( + Pair.create(data.getSong(), data.getArtist()), + () -> { + titleText.setText(data.getSong()); + artistText.setText(data.getArtist()); + + // refreshState is required here to resize the text views (and prevent ellipsis) + mMediaViewController.refreshState(); + + // Use OnPreDrawListeners to enforce zero alpha on these views for a frame. + // TransitionLayout insists on resetting the alpha of these views to 1 when onLayout + // is called which causes the animation to look bad. These suppress that behavior. + titleText.getViewTreeObserver().addOnPreDrawListener( + new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + titleText.setAlpha(0); + titleText.getViewTreeObserver().removeOnPreDrawListener(this); + return true; + } + }); + + artistText.getViewTreeObserver().addOnPreDrawListener( + new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + artistText.setAlpha(0); + artistText.getViewTreeObserver().removeOnPreDrawListener(this); + return true; + } + }); + + return Unit.INSTANCE; + }, + () -> { + // After finishing the enter animation, we refresh state. This could pop if + // something is incorrectly bound, but needs to be run if other elements were + // updated while the enter animation was running + mMediaViewController.refreshState(); + return Unit.INSTANCE; + }); + } - ColorStateList bgColorList = ColorStateList.valueOf(surfaceColor); - ColorStateList accentColorList = ColorStateList.valueOf(accentPrimary); - ColorStateList textColorList = ColorStateList.valueOf(textPrimary); - - // Gradient and background (visible when there is no art) - albumView.setForegroundTintList(ColorStateList.valueOf(surfaceColor)); - albumView.setBackgroundTintList( - ColorStateList.valueOf(surfaceColor)); - mMediaViewHolder.getPlayer().setBackgroundTintList(bgColorList); - - // App icon - use notification icon - ImageView appIconView = mMediaViewHolder.getAppIcon(); - appIconView.clearColorFilter(); - if (data.getAppIcon() != null && !data.getResumption()) { - appIconView.setImageIcon(data.getAppIcon()); - appIconView.setColorFilter(accentPrimary); - } else { - // Resume players use launcher icon - appIconView.setColorFilter(getGrayscaleFilter()); - try { - Drawable icon = mContext.getPackageManager().getApplicationIcon( - data.getPackageName()); - appIconView.setImageDrawable(icon); - } catch (PackageManager.NameNotFoundException e) { - Log.w(TAG, "Cannot find icon for package " + data.getPackageName(), e); - appIconView.setImageResource(R.drawable.ic_music_note); + private void bindArtworkAndColors(MediaData data, boolean updateBackground) { + final int reqId = mArtworkNextBindRequestId++; + + // Capture width & height from views in foreground for artwork scaling in background + int width = mMediaViewHolder.getPlayer().getWidth(); + int height = mMediaViewHolder.getPlayer().getHeight(); + + // WallpaperColors.fromBitmap takes a good amount of time. We do that work + // on the background executor to avoid stalling animations on the UI Thread. + mBackgroundExecutor.execute(() -> { + // Album art + ColorScheme mutableColorScheme = null; + Drawable artwork; + Icon artworkIcon = data.getArtwork(); + if (artworkIcon != null) { + WallpaperColors wallpaperColors = WallpaperColors + .fromBitmap(artworkIcon.getBitmap()); + mutableColorScheme = new ColorScheme(wallpaperColors, true); + artwork = getScaledBackground(artworkIcon, width, height); + } else { + // If there's no artwork, use colors from the app icon + artwork = null; + try { + Drawable icon = mContext.getPackageManager() + .getApplicationIcon(data.getPackageName()); + mutableColorScheme = new ColorScheme(WallpaperColors.fromDrawable(icon), true); + } catch (PackageManager.NameNotFoundException e) { + Log.w(TAG, "Cannot find icon for package " + data.getPackageName(), e); + } } - } - // Metadata text - mMediaViewHolder.getTitleText().setTextColor(textPrimary); - mMediaViewHolder.getArtistText().setTextColor(textSecondary); - - // Seekbar - SeekBar seekbar = mMediaViewHolder.getSeekBar(); - seekbar.getThumb().setTintList(textColorList); - seekbar.setProgressTintList(textColorList); - seekbar.setProgressBackgroundTintList(ColorStateList.valueOf(textTertiary)); - mMediaViewHolder.getScrubbingElapsedTimeView().setTextColor(textColorList); - mMediaViewHolder.getScrubbingTotalTimeView().setTextColor(textColorList); - - // Action buttons - mMediaViewHolder.getActionPlayPause().setBackgroundTintList(accentColorList); - mMediaViewHolder.getActionPlayPause().setImageTintList( - ColorStateList.valueOf(textPrimaryInverse)); - for (ImageButton button : mMediaViewHolder.getTransparentActionButtons()) { - button.setImageTintList(textColorList); - } + final ColorScheme colorScheme = mutableColorScheme; + mMainExecutor.execute(() -> { + // Cancel the request if a later one arrived first + if (reqId < mArtworkBoundId) return; + mArtworkBoundId = reqId; + + // Bind the album view to the artwork or a transition drawable + ImageView albumView = mMediaViewHolder.getAlbumView(); + albumView.setPadding(0, 0, 0, 0); + albumView.setClipToOutline(true); + if (updateBackground) { + if (mPrevArtwork == null || artwork == null) { + albumView.setImageDrawable(artwork); + } else { + TransitionDrawable transitionDrawable = new TransitionDrawable( + new Drawable[] { mPrevArtwork, artwork }); + albumView.setImageDrawable(transitionDrawable); + transitionDrawable.startTransition(333); + } + mPrevArtwork = artwork; + } - // Output switcher - View seamlessView = mMediaViewHolder.getSeamlessButton(); - seamlessView.setBackgroundTintList(accentColorList); - ImageView seamlessIconView = mMediaViewHolder.getSeamlessIcon(); - seamlessIconView.setImageTintList(bgColorList); - TextView seamlessText = mMediaViewHolder.getSeamlessText(); - seamlessText.setTextColor(surfaceColor); - - // Long press buttons - mMediaViewHolder.getLongPressText().setTextColor(textColorList); - mMediaViewHolder.getSettings().setImageTintList(accentColorList); - mMediaViewHolder.getCancelText().setTextColor(textColorList); - mMediaViewHolder.getCancelText().setBackgroundTintList(accentColorList); - mMediaViewHolder.getDismissText().setTextColor(surfaceColor); - mMediaViewHolder.getDismissText().setBackgroundTintList(accentColorList); + // Transition Colors to current color scheme + mColorSchemeTransition.updateColorScheme(colorScheme); + + // App icon - use notification icon + ImageView appIconView = mMediaViewHolder.getAppIcon(); + appIconView.clearColorFilter(); + if (data.getAppIcon() != null && !data.getResumption()) { + appIconView.setImageIcon(data.getAppIcon()); + appIconView.setColorFilter( + mColorSchemeTransition.getAccentPrimary().getTargetColor()); + } else { + // Resume players use launcher icon + appIconView.setColorFilter(getGrayscaleFilter()); + try { + Drawable icon = mContext.getPackageManager() + .getApplicationIcon(data.getPackageName()); + appIconView.setImageDrawable(icon); + } catch (PackageManager.NameNotFoundException e) { + Log.w(TAG, "Cannot find icon for package " + data.getPackageName(), e); + appIconView.setImageResource(R.drawable.ic_music_note); + } + } + }); + }); } private void bindActionButtons(MediaData data) { @@ -713,6 +787,7 @@ public class MediaControlPanel { animHandler.tryExecute(() -> { bindButtonWithAnimations(button, mediaAction, animHandler); setSemanticButtonVisibleAndAlpha(button.getId(), mediaAction, semanticActions); + return Unit.INSTANCE; }); } @@ -785,7 +860,14 @@ public class MediaControlPanel { scrubbingTimeViewsEnabled(semanticActions) && hideWhenScrubbing && mIsScrubbing; boolean visible = mediaAction != null && !shouldBeHiddenDueToScrubbing; - setVisibleAndAlpha(expandedSet, buttonId, visible); + int notVisibleValue; + if ((buttonId == R.id.actionPrev && semanticActions.getReservePrev()) + || (buttonId == R.id.actionNext && semanticActions.getReserveNext())) { + notVisibleValue = ConstraintSet.INVISIBLE; + } else { + notVisibleValue = ConstraintSet.GONE; + } + setVisibleAndAlpha(expandedSet, buttonId, visible, notVisibleValue); setVisibleAndAlpha(collapsedSet, buttonId, visible && showInCompact); } @@ -794,11 +876,12 @@ public class MediaControlPanel { private void updateDisplayForScrubbingChange(@NonNull MediaButton semanticActions) { // Update visibilities of the scrubbing time views and the scrubbing-dependent buttons. bindScrubbingTime(mMediaData); - SEMANTIC_ACTIONS_HIDE_WHEN_SCRUBBING.forEach((id) -> - setSemanticButtonVisibleAndAlpha( - id, semanticActions.getActionById(id), semanticActions)); - // Trigger a state refresh so that we immediately update visibilities. - mMediaViewController.refreshState(); + SEMANTIC_ACTIONS_HIDE_WHEN_SCRUBBING.forEach((id) -> setSemanticButtonVisibleAndAlpha( + id, semanticActions.getActionById(id), semanticActions)); + if (!mMetadataAnimationHandler.isRunning()) { + // Trigger a state refresh so that we immediately update visibilities. + mMediaViewController.refreshState(); + } } private void bindScrubbingTime(MediaData data) { @@ -823,74 +906,6 @@ public class MediaControlPanel { ); } - // AnimationBindHandler is responsible for tracking the bound animation state and preventing - // jank and conflicts due to media notifications arriving at any time during an animation. It - // does this in two parts. - // - Exit animations fired as a result of user input are tracked. When these are running, any - // bind actions are delayed until the animation completes (and then fired in sequence). - // - Continuous animations are tracked using their rebind id. Later calls using the same - // rebind id will be totally ignored to prevent the continuous animation from restarting. - private static class AnimationBindHandler extends Animatable2.AnimationCallback { - private ArrayList<Runnable> mOnAnimationsComplete = new ArrayList<>(); - private ArrayList<Animatable2> mRegistrations = new ArrayList<>(); - private Integer mRebindId = null; - - // This check prevents rebinding to the action button if the identifier has not changed. A - // null value is always considered to be changed. This is used to prevent the connecting - // animation from rebinding (and restarting) if multiple buffer PlaybackStates are pushed by - // an application in a row. - public boolean updateRebindId(Integer rebindId) { - if (mRebindId == null || rebindId == null || !mRebindId.equals(rebindId)) { - mRebindId = rebindId; - return true; - } - return false; - } - - public void tryRegister(Drawable drawable) { - if (drawable instanceof Animatable2) { - Animatable2 anim = (Animatable2) drawable; - anim.registerAnimationCallback(this); - mRegistrations.add(anim); - } - } - - public void unregisterAll() { - for (Animatable2 anim : mRegistrations) { - anim.unregisterAnimationCallback(this); - } - mRegistrations.clear(); - } - - public boolean isAnimationRunning() { - for (Animatable2 anim : mRegistrations) { - if (anim.isRunning()) { - return true; - } - } - return false; - } - - public void tryExecute(Runnable action) { - if (isAnimationRunning()) { - mOnAnimationsComplete.add(action); - } else { - action.run(); - } - } - - @Override - public void onAnimationEnd(Drawable drawable) { - super.onAnimationEnd(drawable); - if (!isAnimationRunning()) { - for (Runnable action : mOnAnimationsComplete) { - action.run(); - } - mOnAnimationsComplete.clear(); - } - } - } - @Nullable private ActivityLaunchAnimator.Controller buildLaunchAnimatorController( TransitionLayout player) { @@ -939,9 +954,11 @@ public class MediaControlPanel { } mSmartspaceId = SmallHash.hash(data.getTargetId()); - mBackgroundColor = data.getBackgroundColor(); + mPackageName = data.getPackageName(); + mInstanceId = data.getInstanceId(); TransitionLayout recommendationCard = mRecommendationViewHolder.getRecommendations(); - recommendationCard.setBackgroundTintList(ColorStateList.valueOf(mBackgroundColor)); + recommendationCard.setBackgroundTintList( + Utils.getColorAttr(mContext, com.android.internal.R.attr.colorSurface)); List<SmartspaceAction> mediaRecommendationList = data.getRecommendations(); if (mediaRecommendationList == null || mediaRecommendationList.isEmpty()) { @@ -963,7 +980,6 @@ public class MediaControlPanel { PackageManager packageManager = mContext.getPackageManager(); // Set up media source app's logo. Drawable icon = packageManager.getApplicationIcon(applicationInfo); - icon.setColorFilter(getGrayscaleFilter()); ImageView headerLogoImageView = mRecommendationViewHolder.getCardIcon(); headerLogoImageView.setImageDrawable(icon); @@ -981,11 +997,6 @@ public class MediaControlPanel { appName = packageManager.getApplicationLabel(applicationInfo); } } - // Set the app name as card's title. - if (!TextUtils.isEmpty(appName)) { - TextView headerTitleText = mRecommendationViewHolder.getCardText(); - headerTitleText.setText(appName); - } // Set up media rec card's tap action if applicable. setSmartspaceRecItemOnClickListener(recommendationCard, data.getCardAction(), @@ -996,11 +1007,6 @@ public class MediaControlPanel { List<ImageView> mediaCoverItems = mRecommendationViewHolder.getMediaCoverItems(); List<ViewGroup> mediaCoverContainers = mRecommendationViewHolder.getMediaCoverContainers(); - List<Integer> mediaCoverItemsResIds = mRecommendationViewHolder.getMediaCoverItemsResIds(); - List<Integer> mediaCoverContainersResIds = - mRecommendationViewHolder.getMediaCoverContainersResIds(); - ConstraintSet expandedSet = mMediaViewController.getExpandedLayout(); - ConstraintSet collapsedSet = mMediaViewController.getCollapsedLayout(); int mediaRecommendationNum = Math.min(mediaRecommendationList.size(), MEDIA_RECOMMENDATION_MAX_NUM); int uiComponentIndex = 0; @@ -1045,21 +1051,28 @@ public class MediaControlPanel { recommendation.getTitle(), artistName, appName)); } - if (uiComponentIndex < MEDIA_RECOMMENDATION_ITEMS_PER_ROW) { - setVisibleAndAlpha(collapsedSet, - mediaCoverItemsResIds.get(uiComponentIndex), true); - setVisibleAndAlpha(collapsedSet, - mediaCoverContainersResIds.get(uiComponentIndex), true); - } else { - setVisibleAndAlpha(collapsedSet, - mediaCoverItemsResIds.get(uiComponentIndex), false); - setVisibleAndAlpha(collapsedSet, - mediaCoverContainersResIds.get(uiComponentIndex), false); - } - setVisibleAndAlpha(expandedSet, - mediaCoverItemsResIds.get(uiComponentIndex), true); - setVisibleAndAlpha(expandedSet, - mediaCoverContainersResIds.get(uiComponentIndex), true); + + // Set up title + CharSequence title = recommendation.getTitle(); + TextView titleView = + mRecommendationViewHolder.getMediaTitles().get(uiComponentIndex); + titleView.setText(title); + titleView.setTextColor(Utils.getColorAttrDefaultColor( + mContext, com.android.internal.R.attr.textColorPrimary)); + // TODO(b/223603970): If none of them have titles, should we then hide the views? + + // Set up subtitle + CharSequence subtitle = recommendation.getSubtitle(); + TextView subtitleView = + mRecommendationViewHolder.getMediaSubtitles().get(uiComponentIndex); + // It would look awkward to show a subtitle if we don't have a title. + boolean shouldShowSubtitleText = !TextUtils.isEmpty(title); + CharSequence subtitleText = shouldShowSubtitleText ? subtitle : ""; + subtitleView.setText(subtitleText); + subtitleView.setTextColor(Utils.getColorAttrDefaultColor( + mContext, com.android.internal.R.attr.textColorSecondary)); + // TODO(b/223603970): If none of them have subtitles, should we then hide the views? + uiComponentIndex++; } @@ -1068,6 +1081,7 @@ public class MediaControlPanel { mRecommendationViewHolder.getDismiss().setOnClickListener(v -> { if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) return; + mLogger.logLongPressDismiss(mUid, mPackageName, mInstanceId); logSmartspaceCardReported( 761 // SMARTSPACE_CARD_DISMISS ); @@ -1093,7 +1107,9 @@ public class MediaControlPanel { }); mController = null; - mMediaViewController.refreshState(); + if (mMetadataAnimationHandler == null || !mMetadataAnimationHandler.isRunning()) { + mMediaViewController.refreshState(); + } } /** @@ -1187,7 +1203,12 @@ public class MediaControlPanel { } private void setVisibleAndAlpha(ConstraintSet set, int actionId, boolean visible) { - set.setVisibility(actionId, visible ? ConstraintSet.VISIBLE : ConstraintSet.GONE); + setVisibleAndAlpha(set, actionId, visible, ConstraintSet.GONE); + } + + private void setVisibleAndAlpha(ConstraintSet set, int actionId, boolean visible, + int notVisibleValue) { + set.setVisibility(actionId, visible ? ConstraintSet.VISIBLE : notVisibleValue); set.setAlpha(actionId, visible ? 1.0f : 0.0f); } @@ -1204,6 +1225,11 @@ public class MediaControlPanel { view.setOnClickListener(v -> { if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) return; + if (interactedSubcardRank == -1) { + mLogger.logRecommendationCardTap(mPackageName, mInstanceId); + } else { + mLogger.logRecommendationItemTap(mPackageName, mInstanceId, interactedSubcardRank); + } logSmartspaceCardReported(SMARTSPACE_CARD_CLICK_EVENT, interactedSubcardRank, getSmartspaceSubCardCardinality()); diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt index bc8cca55154d..d04ec40c9f28 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt @@ -27,7 +27,6 @@ import com.android.systemui.R data class MediaData( val userId: Int, val initialized: Boolean = false, - val backgroundColor: Int, /** * App name that will be displayed on the player. */ @@ -149,23 +148,31 @@ data class MediaButton( /** * Play/pause button */ - var playOrPause: MediaAction? = null, + val playOrPause: MediaAction? = null, /** * Next button, or custom action */ - var nextOrCustom: MediaAction? = null, + val nextOrCustom: MediaAction? = null, /** * Previous button, or custom action */ - var prevOrCustom: MediaAction? = null, + val prevOrCustom: MediaAction? = null, /** * First custom action space */ - var custom0: MediaAction? = null, + val custom0: MediaAction? = null, /** * Second custom action space */ - var custom1: MediaAction? = null + val custom1: MediaAction? = null, + /** + * Whether to reserve the empty space when the nextOrCustom is null + */ + val reserveNext: Boolean = false, + /** + * Whether to reserve the empty space when the prevOrCustom is null + */ + val reservePrev: Boolean = false ) { fun getActionById(id: Int): MediaAction? { return when (id) { diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt index 80a407b9d90f..647d3efa5916 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt @@ -60,7 +60,8 @@ class MediaDataFilter @Inject constructor( private val broadcastSender: BroadcastSender, private val lockscreenUserManager: NotificationLockscreenUserManager, @Main private val executor: Executor, - private val systemClock: SystemClock + private val systemClock: SystemClock, + private val logger: MediaUiEventLogger ) : MediaDataManager.Listener { private val userTracker: CurrentUserTracker private val _listeners: MutableSet<MediaDataManager.Listener> = mutableSetOf() @@ -151,6 +152,8 @@ class MediaDataFilter @Inject constructor( Log.d(TAG, "reactivating $lastActiveKey instead of smartspace") reactivatedKey = lastActiveKey val mediaData = sorted.get(lastActiveKey)!!.copy(active = true) + logger.logRecommendationActivated(mediaData.appUid, mediaData.packageName, + mediaData.instanceId) listeners.forEach { it.onMediaDataLoaded(lastActiveKey, lastActiveKey, mediaData, receivedSmartspaceCardLatency = @@ -167,6 +170,8 @@ class MediaDataFilter @Inject constructor( Log.d(TAG, "Invalid recommendation data. Skip showing the rec card") return } + logger.logRecommendationAdded(smartspaceMediaData.packageName, + smartspaceMediaData.instanceId) listeners.forEach { it.onSmartspaceMediaDataLoaded(key, data, shouldPrioritizeMutable) } } @@ -197,7 +202,9 @@ class MediaDataFilter @Inject constructor( if (smartspaceMediaData.isActive) { smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA.copy( - targetId = smartspaceMediaData.targetId, isValid = smartspaceMediaData.isValid) + targetId = smartspaceMediaData.targetId, + isValid = smartspaceMediaData.isValid, + instanceId = smartspaceMediaData.instanceId) } listeners.forEach { it.onSmartspaceMediaDataRemoved(key, immediately) } } @@ -252,9 +259,12 @@ class MediaDataFilter @Inject constructor( broadcastSender.sendBroadcast(dismissIntent) } smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA.copy( - targetId = smartspaceMediaData.targetId, isValid = smartspaceMediaData.isValid) + targetId = smartspaceMediaData.targetId, + isValid = smartspaceMediaData.isValid, + instanceId = smartspaceMediaData.instanceId) + mediaDataManager.dismissSmartspaceRecommendation(smartspaceMediaData.targetId, + delay = 0L) } - mediaDataManager.dismissSmartspaceRecommendation(smartspaceMediaData.targetId, delay = 0L) } /** diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt index 9a2977d56153..b2751cec5d9e 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt @@ -85,7 +85,6 @@ private const val EXTRAS_SMARTSPACE_DISMISS_INTENT_KEY = "dismiss_intent" private val LOADING = MediaData( userId = -1, initialized = false, - backgroundColor = 0, app = null, appIcon = null, artist = null, @@ -103,8 +102,16 @@ private val LOADING = MediaData( appUid = Process.INVALID_UID) @VisibleForTesting -internal val EMPTY_SMARTSPACE_MEDIA_DATA = SmartspaceMediaData("INVALID", false, false, - "INVALID", null, emptyList(), null, 0, 0) +internal val EMPTY_SMARTSPACE_MEDIA_DATA = SmartspaceMediaData( + targetId = "INVALID", + isActive = false, + isValid = false, + packageName = "INVALID", + cardAction = null, + recommendations = emptyList(), + dismissIntent = null, + headphoneConnectionTimeMillis = 0, + instanceId = InstanceId.fakeInstanceId(-1)) fun isMediaNotification(sbn: StatusBarNotification): Boolean { return sbn.notification.isMediaNotification() @@ -164,15 +171,10 @@ class MediaDataManager( // Maximum number of actions allowed in expanded view @JvmField val MAX_NOTIFICATION_ACTIONS = MediaViewHolder.genericButtonIds.size - - /** Maximum number of [PlaybackState.CustomAction] buttons supported */ - @JvmField - val MAX_CUSTOM_ACTIONS = 4 } private val themeText = com.android.settingslib.Utils.getColorAttr(context, com.android.internal.R.attr.textColorPrimary).defaultColor - private val bgColor = context.getColor(R.color.material_dynamic_secondary95) // Internal listeners are part of the internal pipeline. External listeners (those registered // with [MediaDeviceManager.addListener]) receive events after they have propagated through @@ -532,14 +534,16 @@ class MediaDataManager( * connection session. */ fun dismissSmartspaceRecommendation(key: String, delay: Long) { - if (smartspaceMediaData.targetId != key) { + if (smartspaceMediaData.targetId != key || !smartspaceMediaData.isValid) { + // If this doesn't match, or we've already invalidated the data, no action needed return } if (DEBUG) Log.d(TAG, "Dismissing Smartspace media target") if (smartspaceMediaData.isActive) { smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA.copy( - targetId = smartspaceMediaData.targetId) + targetId = smartspaceMediaData.targetId, + instanceId = smartspaceMediaData.instanceId) } foregroundExecutor.executeDelayed( { notifySmartspaceMediaDataRemoved( @@ -584,7 +588,7 @@ class MediaDataManager( val mediaAction = getResumeMediaAction(resumeAction) val lastActive = systemClock.elapsedRealtime() foregroundExecutor.execute { - onMediaDataLoaded(packageName, null, MediaData(userId, true, bgColor, appName, + onMediaDataLoaded(packageName, null, MediaData(userId, true, appName, null, desc.subtitle, desc.title, artworkIcon, listOf(mediaAction), listOf(0), MediaButton(playOrPause = mediaAction), packageName, token, appIntent, device = null, active = false, @@ -594,14 +598,17 @@ class MediaDataManager( } } - private fun loadMediaDataInBg( + fun loadMediaDataInBg( key: String, sbn: StatusBarNotification, oldKey: String?, logEvent: Boolean = false ) { - val token = sbn.notification.extras.getParcelable(Notification.EXTRA_MEDIA_SESSION) - as MediaSession.Token? + val token = sbn.notification.extras.getParcelable( + Notification.EXTRA_MEDIA_SESSION, MediaSession.Token::class.java) + if (token == null) { + return + } val mediaController = mediaControllerFactory.create(token) val metadata = mediaController.metadata @@ -648,8 +655,8 @@ class MediaDataManager( val extras = sbn.notification.extras val deviceName = extras.getCharSequence(Notification.EXTRA_MEDIA_REMOTE_DEVICE, null) val deviceIcon = extras.getInt(Notification.EXTRA_MEDIA_REMOTE_ICON, -1) - val deviceIntent = extras.getParcelable(Notification.EXTRA_MEDIA_REMOTE_INTENT) - as PendingIntent? + val deviceIntent = extras.getParcelable( + Notification.EXTRA_MEDIA_REMOTE_INTENT, PendingIntent::class.java) Log.d(TAG, "$key is RCN for $deviceName") if (deviceName != null && deviceIcon > -1) { @@ -703,7 +710,7 @@ class MediaDataManager( val resumeAction: Runnable? = mediaEntries[key]?.resumeAction val hasCheckedForResume = mediaEntries[key]?.hasCheckedForResume == true val active = mediaEntries[key]?.active ?: true - onMediaDataLoaded(key, oldKey, MediaData(sbn.normalizedUserId, true, bgColor, app, + onMediaDataLoaded(key, oldKey, MediaData(sbn.normalizedUserId, true, app, smallIcon, artist, song, artWorkIcon, actionIcons, actionsToShowCollapsed, semanticActions, sbn.packageName, token, notif.contentIntent, device, active, resumeAction = resumeAction, playbackLocation = playbackLocation, @@ -784,71 +791,74 @@ class MediaDataManager( */ private fun createActionsFromState(packageName: String, controller: MediaController): MediaButton? { - val actions = MediaButton() - controller.playbackState?.let { state -> - // First, check for standard actions - actions.playOrPause = if (isConnectingState(state.state)) { - // Spinner needs to be animating to render anything. Start it here. - val drawable = context.getDrawable( - com.android.internal.R.drawable.progress_small_material) - (drawable as Animatable).start() - MediaAction( - drawable, - null, // no action to perform when clicked - context.getString(R.string.controls_media_button_connecting), - context.getDrawable(R.drawable.ic_media_connecting_container), - // Specify a rebind id to prevent the spinner from restarting on later binds. - com.android.internal.R.drawable.progress_small_material - ) - } else if (isPlayingState(state.state)) { - getStandardAction(controller, state.actions, PlaybackState.ACTION_PAUSE) - } else { - getStandardAction(controller, state.actions, PlaybackState.ACTION_PLAY) - } - val prevButton = getStandardAction(controller, state.actions, - PlaybackState.ACTION_SKIP_TO_PREVIOUS) - val nextButton = getStandardAction(controller, state.actions, - PlaybackState.ACTION_SKIP_TO_NEXT) - - // Then, check for custom actions - val customActions = MutableList<MediaAction?>(MAX_CUSTOM_ACTIONS) { null } - var customCount = 0 - for (i in 0..(MAX_CUSTOM_ACTIONS - 1)) { - getCustomAction(state, packageName, controller, customCount)?.let { - customActions[customCount++] = it - } - } - - // Finally, assign the remaining button slots: play/pause A B C D - // A = previous, else custom action (if not reserved) - // B = next, else custom action (if not reserved) - // C and D are always custom actions - val reservePrev = controller.extras?.getBoolean( - MediaConstants.SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV) == true - val reserveNext = controller.extras?.getBoolean( - MediaConstants.SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT) == true - var customIdx = 0 - - actions.prevOrCustom = if (prevButton != null) { - prevButton - } else if (!reservePrev) { - customActions[customIdx++] - } else { - null - } - - actions.nextOrCustom = if (nextButton != null) { - nextButton - } else if (!reserveNext) { - customActions[customIdx++] - } else { - null - } + val state = controller.playbackState + if (state == null) { + return MediaButton() + } + // First, check for} standard actions + val playOrPause = if (isConnectingState(state.state)) { + // Spinner needs to be animating to render anything. Start it here. + val drawable = context.getDrawable( + com.android.internal.R.drawable.progress_small_material) + (drawable as Animatable).start() + MediaAction( + drawable, + null, // no action to perform when clicked + context.getString(R.string.controls_media_button_connecting), + context.getDrawable(R.drawable.ic_media_connecting_container), + // Specify a rebind id to prevent the spinner from restarting on later binds. + com.android.internal.R.drawable.progress_small_material + ) + } else if (isPlayingState(state.state)) { + getStandardAction(controller, state.actions, PlaybackState.ACTION_PAUSE) + } else { + getStandardAction(controller, state.actions, PlaybackState.ACTION_PLAY) + } + val prevButton = getStandardAction(controller, state.actions, + PlaybackState.ACTION_SKIP_TO_PREVIOUS) + val nextButton = getStandardAction(controller, state.actions, + PlaybackState.ACTION_SKIP_TO_NEXT) + + // Then, create a way to build any custom actions that will be needed + val customActions = state.customActions.asSequence().filterNotNull().map { + getCustomAction(state, packageName, controller, it) + }.iterator() + fun nextCustomAction() = if (customActions.hasNext()) customActions.next() else null + + // Finally, assign the remaining button slots: play/pause A B C D + // A = previous, else custom action (if not reserved) + // B = next, else custom action (if not reserved) + // C and D are always custom actions + val reservePrev = controller.extras?.getBoolean( + MediaConstants.SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV) == true + val reserveNext = controller.extras?.getBoolean( + MediaConstants.SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT) == true + + val prevOrCustom = if (prevButton != null) { + prevButton + } else if (!reservePrev) { + nextCustomAction() + } else { + null + } - actions.custom0 = customActions[customIdx++] - actions.custom1 = customActions[customIdx++] + val nextOrCustom = if (nextButton != null) { + nextButton + } else if (!reserveNext) { + nextCustomAction() + } else { + null } - return actions + + return MediaButton( + playOrPause, + nextOrCustom, + prevOrCustom, + nextCustomAction(), + nextCustomAction(), + reserveNext, + reservePrev + ) } /** @@ -927,18 +937,12 @@ class MediaDataManager( state: PlaybackState, packageName: String, controller: MediaController, - index: Int - ): MediaAction? { - if (state.customActions.size <= index || state.customActions[index] == null) { - if (DEBUG) { Log.d(TAG, "not enough actions or action was null at $index") } - return null - } - - val it = state.customActions[index] + customAction: PlaybackState.CustomAction + ): MediaAction { return MediaAction( - Icon.createWithResource(packageName, it.icon).loadDrawable(context), - { controller.transportControls.sendCustomAction(it, it.extras) }, - it.name, + Icon.createWithResource(packageName, customAction.icon).loadDrawable(context), + { controller.transportControls.sendCustomAction(customAction, customAction.extras) }, + customAction.name, null ) } @@ -1035,7 +1039,8 @@ class MediaDataManager( Log.d(TAG, "Set Smartspace media to be inactive for the data update") } smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA.copy( - targetId = smartspaceMediaData.targetId) + targetId = smartspaceMediaData.targetId, + instanceId = smartspaceMediaData.instanceId) notifySmartspaceMediaDataRemoved(smartspaceMediaData.targetId, immediately = false) } 1 -> { @@ -1214,15 +1219,23 @@ class MediaDataManager( .getParcelable(EXTRAS_SMARTSPACE_DISMISS_INTENT_KEY) as Intent? } packageName(target)?.let { - return SmartspaceMediaData(target.smartspaceTargetId, isActive, true, it, - target.baseAction, target.iconGrid, - dismissIntent, 0, target.creationTimeMillis) + return SmartspaceMediaData( + targetId = target.smartspaceTargetId, + isActive = isActive, + isValid = true, + packageName = it, + cardAction = target.baseAction, + recommendations = target.iconGrid, + dismissIntent = dismissIntent, + headphoneConnectionTimeMillis = target.creationTimeMillis, + instanceId = logger.getNewInstanceId()) } return EMPTY_SMARTSPACE_MEDIA_DATA .copy(targetId = target.smartspaceTargetId, isActive = isActive, dismissIntent = dismissIntent, - headphoneConnectionTimeMillis = target.creationTimeMillis) + headphoneConnectionTimeMillis = target.creationTimeMillis, + instanceId = logger.getNewInstanceId()) } private fun packageName(target: SmartspaceTarget): String? { diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaUiEventLogger.kt b/packages/SystemUI/src/com/android/systemui/media/MediaUiEventLogger.kt index 3eba3b55b7e8..52f5cc568ba4 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaUiEventLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaUiEventLogger.kt @@ -151,6 +151,31 @@ class MediaUiEventLogger @Inject constructor(private val logger: UiEventLogger) } logger.log(event) } + + fun logRecommendationAdded(packageName: String, instanceId: InstanceId) { + logger.logWithInstanceId(MediaUiEvent.MEDIA_RECOMMENDATION_ADDED, 0, packageName, + instanceId) + } + + fun logRecommendationRemoved(packageName: String, instanceId: InstanceId) { + logger.logWithInstanceId(MediaUiEvent.MEDIA_RECOMMENDATION_REMOVED, 0, packageName, + instanceId) + } + + fun logRecommendationActivated(uid: Int, packageName: String, instanceId: InstanceId) { + logger.logWithInstanceId(MediaUiEvent.MEDIA_RECOMMENDATION_ACTIVATED, uid, packageName, + instanceId) + } + + fun logRecommendationItemTap(packageName: String, instanceId: InstanceId, position: Int) { + logger.logWithInstanceIdAndPosition(MediaUiEvent.MEDIA_RECOMMENDATION_ITEM_TAP, 0, + packageName, instanceId, position) + } + + fun logRecommendationCardTap(packageName: String, instanceId: InstanceId) { + logger.logWithInstanceId(MediaUiEvent.MEDIA_RECOMMENDATION_CARD_TAP, 0, packageName, + instanceId) + } } enum class MediaUiEvent(val metricId: Int) : UiEventLogger.UiEventEnum { @@ -233,7 +258,22 @@ enum class MediaUiEvent(val metricId: Int) : UiEventLogger.UiEventEnum { MEDIA_CAROUSEL_LOCATION_LOCKSCREEN(1039), @UiEvent(doc = "The media carousel moved to the dream state") - MEDIA_CAROUSEL_LOCATION_DREAM(1040); + MEDIA_CAROUSEL_LOCATION_DREAM(1040), + + @UiEvent(doc = "A media recommendation card was added to the media carousel") + MEDIA_RECOMMENDATION_ADDED(1041), + + @UiEvent(doc = "A media recommendation card was removed from the media carousel") + MEDIA_RECOMMENDATION_REMOVED(1042), + + @UiEvent(doc = "An existing media control was made active as a recommendation") + MEDIA_RECOMMENDATION_ACTIVATED(1043), + + @UiEvent(doc = "User tapped on an item in a media recommendation card") + MEDIA_RECOMMENDATION_ITEM_TAP(1044), + + @UiEvent(doc = "User tapped on a media recommendation card") + MEDIA_RECOMMENDATION_CARD_TAP(1045); override fun getId() = metricId }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/media/MetadataAnimationHandler.kt b/packages/SystemUI/src/com/android/systemui/media/MetadataAnimationHandler.kt new file mode 100644 index 000000000000..9a1a6d35e3e3 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/MetadataAnimationHandler.kt @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media + +import android.animation.Animator +import android.animation.AnimatorListenerAdapter +import android.animation.AnimatorSet +import com.android.internal.annotations.VisibleForTesting + +/** + * MetadataAnimationHandler controls the current state of the MediaControlPanel's transition motion. + * + * It checks for a changed data object (artist & title from MediaControlPanel) and runs the + * animation if necessary. When the motion has fully transitioned the elements out, it runs the + * update callback to modify the view data, before the enter animation runs. + */ +internal open class MetadataAnimationHandler( + private val exitAnimator: Animator, + private val enterAnimator: Animator +) : AnimatorListenerAdapter() { + + private val animator: AnimatorSet + private var postExitUpdate: (() -> Unit)? = null + private var postEnterUpdate: (() -> Unit)? = null + private var targetData: Any? = null + + val isRunning: Boolean + get() = animator.isRunning + + fun setNext(targetData: Any, postExit: () -> Unit, postEnter: () -> Unit): Boolean { + if (targetData != this.targetData) { + this.targetData = targetData + postExitUpdate = postExit + postEnterUpdate = postEnter + if (!animator.isRunning) { + animator.start() + } + return true + } + return false + } + + override fun onAnimationEnd(animator: Animator) { + if (animator === exitAnimator) { + postExitUpdate?.let { it() } + postExitUpdate = null + } + + if (animator === enterAnimator) { + // Another new update appeared while entering + if (postExitUpdate != null) { + this.animator.start() + } else { + postEnterUpdate?.let { it() } + postEnterUpdate = null + } + } + } + + init { + exitAnimator.addListener(this) + enterAnimator.addListener(this) + animator = buildAnimatorSet(exitAnimator, enterAnimator) + } + + @VisibleForTesting + protected open fun buildAnimatorSet(exit: Animator, enter: Animator): AnimatorSet { + val result = AnimatorSet() + result.playSequentially(exitAnimator, enterAnimator) + return result + } +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt index c0f79d575dc6..a83984036f60 100644 --- a/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt +++ b/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt @@ -31,35 +31,26 @@ class RecommendationViewHolder private constructor(itemView: View) { // Recommendation screen val cardIcon = itemView.requireViewById<ImageView>(R.id.recommendation_card_icon) - val cardText = itemView.requireViewById<TextView>(R.id.recommendation_card_text) val mediaCoverItems = listOf<ImageView>( itemView.requireViewById(R.id.media_cover1), itemView.requireViewById(R.id.media_cover2), - itemView.requireViewById(R.id.media_cover3), - itemView.requireViewById(R.id.media_cover4), - itemView.requireViewById(R.id.media_cover5), - itemView.requireViewById(R.id.media_cover6)) + itemView.requireViewById(R.id.media_cover3) + ) val mediaCoverContainers = listOf<ViewGroup>( itemView.requireViewById(R.id.media_cover1_container), itemView.requireViewById(R.id.media_cover2_container), - itemView.requireViewById(R.id.media_cover3_container), - itemView.requireViewById(R.id.media_cover4_container), - itemView.requireViewById(R.id.media_cover5_container), - itemView.requireViewById(R.id.media_cover6_container)) - val mediaCoverItemsResIds = listOf<Int>( - R.id.media_cover1, - R.id.media_cover2, - R.id.media_cover3, - R.id.media_cover4, - R.id.media_cover5, - R.id.media_cover6) - val mediaCoverContainersResIds = listOf<Int>( - R.id.media_cover1_container, - R.id.media_cover2_container, - R.id.media_cover3_container, - R.id.media_cover4_container, - R.id.media_cover5_container, - R.id.media_cover6_container) + itemView.requireViewById(R.id.media_cover3_container) + ) + val mediaTitles: List<TextView> = listOf( + itemView.requireViewById(R.id.media_title1), + itemView.requireViewById(R.id.media_title2), + itemView.requireViewById(R.id.media_title3) + ) + val mediaSubtitles: List<TextView> = listOf( + itemView.requireViewById(R.id.media_subtitle1), + itemView.requireViewById(R.id.media_subtitle2), + itemView.requireViewById(R.id.media_subtitle3) + ) // Settings/Guts screen val longPressText = itemView.requireViewById<TextView>(R.id.remove_text) @@ -107,19 +98,12 @@ class RecommendationViewHolder private constructor(itemView: View) { // Res Ids for the control components on the recommendation view. val controlsIds = setOf( R.id.recommendation_card_icon, - R.id.recommendation_card_text, R.id.media_cover1, R.id.media_cover2, R.id.media_cover3, - R.id.media_cover4, - R.id.media_cover5, - R.id.media_cover6, R.id.media_cover1_container, R.id.media_cover2_container, R.id.media_cover3_container, - R.id.media_cover4_container, - R.id.media_cover5_container, - R.id.media_cover6_container ) // Res Ids for the components on the guts panel. diff --git a/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt b/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt index 612a7f92fc33..60ef85d0b502 100644 --- a/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt +++ b/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt @@ -16,20 +16,29 @@ package com.android.systemui.media +import android.animation.Animator +import android.animation.ObjectAnimator import android.text.format.DateUtils import androidx.annotation.UiThread import androidx.lifecycle.Observer +import com.android.internal.annotations.VisibleForTesting import com.android.systemui.R +import com.android.systemui.animation.Interpolators /** * Observer for changes from SeekBarViewModel. * * <p>Updates the seek bar views in response to changes to the model. */ -class SeekBarObserver( +open class SeekBarObserver( private val holder: MediaViewHolder ) : Observer<SeekBarViewModel.Progress> { + companion object { + @JvmStatic val RESET_ANIMATION_DURATION_MS: Int = 750 + @JvmStatic val RESET_ANIMATION_THRESHOLD_MS: Int = 250 + } + val seekBarEnabledMaxHeight = holder.seekBar.context.resources .getDimensionPixelSize(R.dimen.qs_media_enabled_seekbar_height) val seekBarDisabledHeight = holder.seekBar.context.resources @@ -38,6 +47,7 @@ class SeekBarObserver( .getDimensionPixelSize(R.dimen.qs_media_session_enabled_seekbar_vertical_padding) val seekBarDisabledVerticalPadding = holder.seekBar.context.resources .getDimensionPixelSize(R.dimen.qs_media_session_disabled_seekbar_vertical_padding) + var seekBarResetAnimator: Animator? = null init { val seekBarProgressWavelength = holder.seekBar.context.resources @@ -79,6 +89,7 @@ class SeekBarObserver( holder.seekBar.thumb.alpha = if (data.seekAvailable) 255 else 0 holder.seekBar.isEnabled = data.seekAvailable progressDrawable?.animate = data.playing && !data.scrubbing + progressDrawable?.transitionEnabled = !data.seekAvailable if (holder.seekBar.maxHeight != seekBarEnabledMaxHeight) { holder.seekBar.maxHeight = seekBarEnabledMaxHeight @@ -91,7 +102,17 @@ class SeekBarObserver( holder.scrubbingTotalTimeView.text = totalTimeString data.elapsedTime?.let { - holder.seekBar.setProgress(it) + if (!data.scrubbing && !(seekBarResetAnimator?.isRunning ?: false)) { + if (it <= RESET_ANIMATION_THRESHOLD_MS && + holder.seekBar.progress > RESET_ANIMATION_THRESHOLD_MS) { + // This animation resets for every additional update to zero. + val animator = buildResetAnimator(it) + animator.start() + seekBarResetAnimator = animator + } else { + holder.seekBar.progress = it + } + } val elapsedTimeString = DateUtils.formatElapsedTime( it / DateUtils.SECOND_IN_MILLIS) holder.scrubbingElapsedTimeView.text = elapsedTimeString @@ -104,6 +125,16 @@ class SeekBarObserver( } } + @VisibleForTesting + open fun buildResetAnimator(targetTime: Int): Animator { + val animator = ObjectAnimator.ofInt(holder.seekBar, "progress", + holder.seekBar.progress, targetTime + RESET_ANIMATION_DURATION_MS) + animator.setAutoCancel(true) + animator.duration = RESET_ANIMATION_DURATION_MS.toLong() + animator.interpolator = Interpolators.EMPHASIZED + return animator + } + @UiThread fun setVerticalPadding(padding: Int) { val leftPadding = holder.seekBar.paddingLeft diff --git a/packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaData.kt b/packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaData.kt index 066a6fbfa8be..930c5a8de125 100644 --- a/packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaData.kt +++ b/packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaData.kt @@ -18,6 +18,7 @@ package com.android.systemui.media import android.app.smartspace.SmartspaceAction import android.content.Intent +import com.android.internal.logging.InstanceId /** State of a Smartspace media recommendations view. */ data class SmartspaceMediaData( @@ -50,11 +51,11 @@ data class SmartspaceMediaData( */ val dismissIntent: Intent?, /** - * View's background color. + * The timestamp in milliseconds that headphone is connected. */ - val backgroundColor: Int, + val headphoneConnectionTimeMillis: Long, /** - * The timestamp in milliseconds that headphone is connected. + * Instance ID for [MediaUiEventLogger] */ - val headphoneConnectionTimeMillis: Long + val instanceId: InstanceId ) diff --git a/packages/SystemUI/src/com/android/systemui/media/SquigglyProgress.kt b/packages/SystemUI/src/com/android/systemui/media/SquigglyProgress.kt index fbd17d7a212e..88f6f3dd9d0e 100644 --- a/packages/SystemUI/src/com/android/systemui/media/SquigglyProgress.kt +++ b/packages/SystemUI/src/com/android/systemui/media/SquigglyProgress.kt @@ -5,13 +5,15 @@ import android.animation.AnimatorListenerAdapter import android.animation.ValueAnimator import android.content.res.ColorStateList import android.graphics.Canvas -import android.graphics.Color import android.graphics.ColorFilter import android.graphics.Paint import android.graphics.Path import android.graphics.PixelFormat import android.graphics.drawable.Drawable import android.os.SystemClock +import android.util.MathUtils.lerp +import android.util.MathUtils.lerpInv +import android.util.MathUtils.lerpInvSat import androidx.annotation.VisibleForTesting import com.android.internal.graphics.ColorUtils import com.android.systemui.animation.Interpolators @@ -34,6 +36,13 @@ class SquigglyProgress : Drawable() { private var phaseOffset = 0f private var lastFrameTime = -1L + /* distance over which amplitude drops to zero, measured in wavelengths */ + private val transitionPeriods = 1.5f + /* wave endpoint as percentage of bar when play position is zero */ + private val minWaveEndpoint = 0.2f + /* wave endpoint as percentage of bar when play position matches wave endpoint */ + private val matchedWaveEndpoint = 0.6f + // Horizontal length of the sine wave var waveLength = 0f // Height of each peak of the sine wave @@ -51,6 +60,12 @@ class SquigglyProgress : Drawable() { linePaint.strokeWidth = value } + var transitionEnabled = true + set(value) { + field = value + invalidateSelf() + } + init { wavePaint.strokeCap = Paint.Cap.ROUND linePaint.strokeCap = Paint.Cap.ROUND @@ -95,57 +110,90 @@ class SquigglyProgress : Drawable() { if (animate) { invalidateSelf() val now = SystemClock.uptimeMillis() - phaseOffset -= (now - lastFrameTime) / 1000f * phaseSpeed + phaseOffset += (now - lastFrameTime) / 1000f * phaseSpeed phaseOffset %= waveLength lastFrameTime = now } - val totalProgressPx = (bounds.width() * (level / 10_000f)) + val progress = level / 10_000f + val totalProgressPx = bounds.width() * progress + val waveProgressPx = bounds.width() * ( + if (!transitionEnabled || progress > matchedWaveEndpoint) progress else + lerp(minWaveEndpoint, matchedWaveEndpoint, lerpInv(0f, matchedWaveEndpoint, progress))) + + // Build Wiggly Path + val waveStart = -phaseOffset + val waveEnd = waveProgressPx + val transitionLength = if (transitionEnabled) transitionPeriods * waveLength else 0.01f + + // helper function, computes amplitude for wave segment + val computeAmplitude: (Float, Float) -> Float = { x, sign -> + sign * heightFraction * lineAmplitude * + lerpInvSat(waveEnd, waveEnd - transitionLength, x) + } + + var currentX = waveEnd + var waveSign = if (phaseOffset < waveLength / 2) 1f else -1f + path.rewind() + + // Draw flat line from end to wave endpoint + path.moveTo(bounds.width().toFloat(), 0f) + path.lineTo(waveEnd, 0f) + + // First wave has shortened wavelength + // approx quarter wave gets us to first wave peak + // shouldn't be big enough to notice it's not a sin wave + currentX -= phaseOffset % (waveLength / 2) + val controlRatio = 0.25f + var currentAmp = computeAmplitude(currentX, waveSign) + path.cubicTo( + waveEnd, currentAmp * controlRatio, + lerp(currentX, waveEnd, controlRatio), currentAmp, + currentX, currentAmp) + + // Other waves have full wavelength + val dist = -1 * waveLength / 2f + while (currentX > waveStart) { + waveSign = -waveSign + val nextX = currentX + dist + val midX = currentX + dist / 2 + val nextAmp = computeAmplitude(nextX, waveSign) + path.cubicTo( + midX, currentAmp, + midX, nextAmp, + nextX, nextAmp) + currentAmp = nextAmp + currentX = nextX + } + + // Draw path; clip to progress position canvas.save() canvas.translate(bounds.left.toFloat(), bounds.centerY().toFloat()) - // Clip drawing, so we stop at the thumb canvas.clipRect( 0f, -lineAmplitude - strokeWidth, totalProgressPx, lineAmplitude + strokeWidth) - - // The squiggly line - val start = phaseOffset - var currentX = start - var waveSign = 1f - path.rewind() - path.moveTo(start, lineAmplitude * heightFraction) - while (currentX < totalProgressPx) { - val nextX = currentX + waveLength / 2f - val nextWaveSign = waveSign * -1 - path.cubicTo( - currentX + waveLength / 4f, lineAmplitude * waveSign * heightFraction, - nextX - waveLength / 4f, lineAmplitude * nextWaveSign * heightFraction, - nextX, lineAmplitude * nextWaveSign * heightFraction) - currentX = nextX - waveSign = nextWaveSign - } - wavePaint.style = Paint.Style.STROKE canvas.drawPath(path, wavePaint) canvas.restore() + // Draw path; clip between progression position & far edge + canvas.save() + canvas.translate(bounds.left.toFloat(), bounds.centerY().toFloat()) + canvas.clipRect( + totalProgressPx, + -lineAmplitude - strokeWidth, + bounds.width().toFloat(), + lineAmplitude + strokeWidth) + canvas.drawPath(path, linePaint) + canvas.restore() + // Draw round line cap at the beginning of the wave - val startAmp = cos(abs(phaseOffset) / waveLength * TWO_PI) - val p = Paint() - p.color = Color.WHITE + val startAmp = cos(abs(waveEnd - phaseOffset) / waveLength * TWO_PI) canvas.drawPoint( bounds.left.toFloat(), bounds.centerY() + startAmp * lineAmplitude * heightFraction, wavePaint) - - // Draw continuous line, to the right of the thumb - canvas.drawLine( - bounds.left.toFloat() + totalProgressPx, - bounds.centerY().toFloat(), - bounds.width().toFloat(), - bounds.centerY().toFloat(), - linePaint) } override fun getOpacity(): Int { diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java index 0edadcc82a24..ddcba3ae65ae 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java @@ -117,7 +117,9 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { } mCheckBox.setVisibility(View.GONE); mStatusIcon.setVisibility(View.GONE); + mEndTouchArea.setVisibility(View.GONE); mContainerLayout.setOnClickListener(null); + mContainerLayout.setContentDescription(null); mTitleText.setTextColor(mController.getColorItemContent()); mSubTitleText.setTextColor(mController.getColorItemContent()); mTwoLineTitleText.setTextColor(mController.getColorItemContent()); @@ -168,12 +170,17 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { setSingleLineLayout(getItemTitle(device), true /* bFocused */, true /* showSeekBar */, false /* showProgressBar */, false /* showStatus */); + setUpContentDescriptionForActiveDevice(device); + mCheckBox.setOnCheckedChangeListener(null); mCheckBox.setVisibility(View.VISIBLE); mCheckBox.setChecked(true); - mSeekBar.setOnClickListener(null); - mSeekBar.setOnClickListener(v -> onGroupActionTriggered(false, device)); + mCheckBox.setOnCheckedChangeListener( + (buttonView, isChecked) -> onGroupActionTriggered(false, device)); setCheckBoxColor(mCheckBox, mController.getColorItemContent()); initSeekbar(device); + mEndTouchArea.setVisibility(View.VISIBLE); + mEndTouchArea.setOnClickListener(null); + mEndTouchArea.setOnClickListener((v) -> mCheckBox.performClick()); } else if (!mController.hasAdjustVolumeUserRestriction() && currentlyConnected) { mStatusIcon.setImageDrawable( mContext.getDrawable(R.drawable.media_output_status_check)); @@ -183,10 +190,15 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { true /* showSeekBar */, false /* showProgressBar */, true /* showStatus */); initSeekbar(device); + setUpContentDescriptionForActiveDevice(device); mCurrentActivePosition = position; } else if (isDeviceIncluded(mController.getSelectableMediaDevice(), device)) { + mCheckBox.setOnCheckedChangeListener(null); mCheckBox.setVisibility(View.VISIBLE); mCheckBox.setChecked(false); + mCheckBox.setOnCheckedChangeListener( + (buttonView, isChecked) -> onGroupActionTriggered(true, device)); + mEndTouchArea.setVisibility(View.VISIBLE); mContainerLayout.setOnClickListener(v -> onGroupActionTriggered(true, device)); setCheckBoxColor(mCheckBox, mController.getColorItemContent()); setSingleLineLayout(getItemTitle(device), false /* bFocused */, @@ -245,5 +257,14 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { notifyDataSetChanged(); } } + + private void setUpContentDescriptionForActiveDevice(MediaDevice device) { + mContainerLayout.setClickable(false); + mContainerLayout.setContentDescription( + mContext.getString(device.getDeviceType() + == MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE + ? R.string.accessibility_bluetooth_name + : R.string.accessibility_cast_name, device.getName())); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java index 5c536d469212..9dc29bd6e090 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java @@ -144,6 +144,7 @@ public abstract class MediaOutputBaseAdapter extends final LinearLayout mTwoLineLayout; final ImageView mStatusIcon; final CheckBox mCheckBox; + final LinearLayout mEndTouchArea; private String mDeviceId; MediaDeviceBaseViewHolder(View view) { @@ -159,6 +160,7 @@ public abstract class MediaOutputBaseAdapter extends mSeekBar = view.requireViewById(R.id.volume_seekbar); mStatusIcon = view.requireViewById(R.id.media_output_item_status); mCheckBox = view.requireViewById(R.id.check_box); + mEndTouchArea = view.requireViewById(R.id.end_action_area); } void onBind(MediaDevice device, boolean topMargin, boolean bottomMargin, int position) { diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java index 3cffd0266ac8..fc1039780419 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java @@ -88,8 +88,11 @@ public class MediaOutputDialog extends MediaOutputBaseDialog { @Override int getStopButtonVisibility() { - boolean isActiveRemoteDevice = mMediaOutputController.isActiveRemoteDevice( - mMediaOutputController.getCurrentConnectedMediaDevice()); + boolean isActiveRemoteDevice = false; + if (mMediaOutputController.getCurrentConnectedMediaDevice() != null) { + isActiveRemoteDevice = mMediaOutputController.isActiveRemoteDevice( + mMediaOutputController.getCurrentConnectedMediaDevice()); + } boolean isBroadCastSupported = isBroadcastSupported(); return (isActiveRemoteDevice || isBroadCastSupported) ? View.VISIBLE : View.GONE; diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSeekbar.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSeekbar.java deleted file mode 100644 index 0a3c5bf24b8b..000000000000 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSeekbar.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.media.dialog; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.widget.SeekBar; - -/** - * Customized seekbar used by MediaOutputDialog, which only changes progress when dragging, - * otherwise performs click. - */ -public class MediaOutputSeekbar extends SeekBar { - private static final int DRAGGING_THRESHOLD = 20; - private boolean mIsDragging = false; - - public MediaOutputSeekbar(Context context) { - super(context); - } - - public MediaOutputSeekbar(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - int width = getWidth() - - getPaddingLeft() - - getPaddingRight(); - int thumbPos = getPaddingLeft() - + width - * getProgress() - / getMax(); - if (event.getAction() == MotionEvent.ACTION_DOWN - && Math.abs(event.getX() - thumbPos) < DRAGGING_THRESHOLD) { - mIsDragging = true; - super.onTouchEvent(event); - } else if (event.getAction() == MotionEvent.ACTION_MOVE && mIsDragging) { - super.onTouchEvent(event); - } else if (event.getAction() == MotionEvent.ACTION_UP && mIsDragging) { - mIsDragging = false; - super.onTouchEvent(event); - } else if (event.getAction() == MotionEvent.ACTION_UP && !mIsDragging) { - performClick(); - } - return true; - } - - @Override - public boolean performClick() { - return super.performClick(); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ChipStateReceiver.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ChipStateReceiver.kt index a0e803f6bb8d..40ea1e6e87df 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ChipStateReceiver.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ChipStateReceiver.kt @@ -17,6 +17,7 @@ package com.android.systemui.media.taptotransfer.receiver import android.app.StatusBarManager +import android.util.Log import com.android.internal.logging.UiEventLogger /** @@ -25,15 +26,15 @@ import com.android.internal.logging.UiEventLogger */ enum class ChipStateReceiver( @StatusBarManager.MediaTransferSenderState val stateInt: Int, - val uiEvent: UiEventLogger.UiEventEnum, + val uiEvent: UiEventLogger.UiEventEnum ) { CLOSE_TO_SENDER( StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_CLOSE_TO_SENDER, - MediaTttReceiverUiEvents.MEDIA_TTT_RECEIVER_CLOSE_TO_SENDER, + MediaTttReceiverUiEvents.MEDIA_TTT_RECEIVER_CLOSE_TO_SENDER ), FAR_FROM_SENDER( StatusBarManager.MEDIA_TRANSFER_RECEIVER_STATE_FAR_FROM_SENDER, - MediaTttReceiverUiEvents.MEDIA_TTT_RECEIVER_FAR_FROM_SENDER, + MediaTttReceiverUiEvents.MEDIA_TTT_RECEIVER_FAR_FROM_SENDER ); companion object { @@ -43,8 +44,13 @@ enum class ChipStateReceiver( */ fun getReceiverStateFromId( @StatusBarManager.MediaTransferReceiverState displayState: Int - ) : ChipStateReceiver = values().first { it.stateInt == displayState } - + ): ChipStateReceiver? = + try { + values().first { it.stateInt == displayState } + } catch (e: NoSuchElementException) { + Log.e(TAG, "Could not find requested state $displayState", e) + null + } /** * Returns the state int from [StatusBarManager] associated with the given sender state @@ -56,3 +62,5 @@ enum class ChipStateReceiver( fun getReceiverStateIdFromName(name: String): Int = valueOf(name).stateInt } } + +private const val TAG = "ChipStateReceiver" diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index 0f45a7562d0c..740ecff6b06e 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -83,6 +83,7 @@ import android.util.Log; import android.view.Display; import android.view.Gravity; import android.view.HapticFeedbackConstants; +import android.view.InsetsState; import android.view.InsetsState.InternalInsetsType; import android.view.InsetsVisibilities; import android.view.KeyEvent; @@ -196,6 +197,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements private final Optional<Pip> mPipOptional; private final Optional<Recents> mRecentsOptional; private final DeviceConfigProxy mDeviceConfigProxy; + private final NavigationBarTransitions mNavigationBarTransitions; private final Optional<BackAnimation> mBackAnimation; private final Handler mHandler; private final NavigationBarOverlayController mNavbarOverlayController; @@ -512,6 +514,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements InputMethodManager inputMethodManager, DeadZone deadZone, DeviceConfigProxy deviceConfigProxy, + NavigationBarTransitions navigationBarTransitions, Optional<BackAnimation> backAnimation) { super(navigationBarView); mFrame = navigationBarFrame; @@ -536,6 +539,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements mRecentsOptional = recentsOptional; mDeadZone = deadZone; mDeviceConfigProxy = deviceConfigProxy; + mNavigationBarTransitions = navigationBarTransitions; mBackAnimation = backAnimation; mHandler = mainHandler; mNavbarOverlayController = navbarOverlayController; @@ -560,6 +564,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements public void onInit() { // TODO: A great deal of this code should probably live in onViewAttached. // It should also has corresponding cleanup in onViewDetached. + mView.setBarTransitions(mNavigationBarTransitions); mView.setTouchHandler(mTouchHandler); mView.setNavBarMode(mNavBarMode); mView.updateRotationButton(); @@ -631,7 +636,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements mView.setOnVerticalChangedListener(this::onVerticalChanged); mView.setOnTouchListener(this::onNavigationTouch); if (mSavedState != null) { - mView.getLightTransitionsController().restoreState(mSavedState); + getBarTransitions().getLightTransitionsController().restoreState(mSavedState); } setNavigationIconHints(mNavigationIconHints); mView.setWindowVisible(isNavBarWindowVisible()); @@ -704,8 +709,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements mView.getRotationButtonController(); rotationButtonController.setRotationCallback(null); mView.setUpdateActiveTouchRegionsCallback(null); - mView.getBarTransitions().destroy(); - mView.getLightTransitionsController().destroy(mContext); + getBarTransitions().destroy(); mOverviewProxyService.removeCallback(mOverviewProxyListener); mBroadcastDispatcher.unregisterReceiver(mBroadcastReceiver); if (mOrientationHandle != null) { @@ -731,7 +735,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements outState.putInt(EXTRA_APPEARANCE, mAppearance); outState.putInt(EXTRA_BEHAVIOR, mBehavior); outState.putBoolean(EXTRA_TRANSIENT_STATE, mTransientShown); - mView.getLightTransitionsController().saveState(outState); + getBarTransitions().getLightTransitionsController().saveState(outState); } /** @@ -892,7 +896,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements pw.println(" mTransientShown=" + mTransientShown); pw.println(" mTransientShownFromGestureOnSystemBar=" + mTransientShownFromGestureOnSystemBar); - dumpBarTransitions(pw, "mNavigationBarView", mView.getBarTransitions()); + dumpBarTransitions(pw, "mNavigationBarView", getBarTransitions()); mView.dump(pw); } @@ -1429,7 +1433,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements mLightBarController = lightBarController; if (mLightBarController != null) { mLightBarController.setNavigationBar( - mView.getLightTransitionsController()); + getBarTransitions().getLightTransitionsController()); } } @@ -1471,7 +1475,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements mCentralSurfacesOptionalLazy.get().map(CentralSurfaces::isDeviceInteractive) .orElse(false) && mNavigationBarWindowState != WINDOW_STATE_HIDDEN; - mView.getBarTransitions().transitionTo(mTransitionMode, anim); + getBarTransitions().transitionTo(mTransitionMode, anim); } public void disableAnimationsDuringHide(long delay) { @@ -1491,11 +1495,11 @@ public class NavigationBar extends ViewController<NavigationBarView> implements } public NavigationBarTransitions getBarTransitions() { - return mView.getBarTransitions(); + return mNavigationBarTransitions; } public void finishBarAnimations() { - mView.getBarTransitions().finishAnimations(); + getBarTransitions().finishAnimations(); } private WindowManager.LayoutParams getBarLayoutParams(int rotation) { @@ -1558,10 +1562,12 @@ public class NavigationBar extends ViewController<NavigationBarView> implements | WindowManager.LayoutParams.FLAG_SLIPPERY, PixelFormat.TRANSLUCENT); lp.gravity = gravity; + lp.providedInternalInsets = new Insets[InsetsState.SIZE]; if (insetsHeight != -1) { - lp.providedInternalInsets = Insets.of(0, height - insetsHeight, 0, 0); + lp.providedInternalInsets[ITYPE_NAVIGATION_BAR] = + Insets.of(0, height - insetsHeight, 0, 0); } else { - lp.providedInternalInsets = Insets.NONE; + lp.providedInternalInsets[ITYPE_NAVIGATION_BAR] = null; } lp.token = new Binder(); lp.accessibilityTitle = mContext.getString(R.string.nav_bar); diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java index 58e07db09c62..e625501d8961 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java @@ -31,17 +31,19 @@ import android.view.View; import com.android.systemui.Dependency; import com.android.systemui.R; +import com.android.systemui.navigationbar.NavigationBarComponent.NavigationBarScope; import com.android.systemui.navigationbar.buttons.ButtonDispatcher; -import com.android.systemui.plugins.statusbar.StatusBarStateController; -import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.phone.BarTransitions; import com.android.systemui.statusbar.phone.LightBarTransitionsController; -import com.android.systemui.statusbar.policy.KeyguardStateController; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; +import javax.inject.Inject; + +/** */ +@NavigationBarScope public final class NavigationBarTransitions extends BarTransitions implements LightBarTransitionsController.DarkIntensityApplier { @@ -81,15 +83,13 @@ public final class NavigationBarTransitions extends BarTransitions implements } }; - public NavigationBarTransitions(NavigationBarView view, CommandQueue commandQueue) { + @Inject + public NavigationBarTransitions( + NavigationBarView view, + LightBarTransitionsController.Factory lightBarTransitionsControllerFactory) { super(view, R.drawable.nav_background); mView = view; - mLightTransitionsController = new LightBarTransitionsController( - view.getContext(), - this, - commandQueue, - Dependency.get(KeyguardStateController.class), - Dependency.get(StatusBarStateController.class)); + mLightTransitionsController = lightBarTransitionsControllerFactory.create(this); mAllowAutoDimWallpaperNotVisible = view.getContext().getResources() .getBoolean(R.bool.config_navigation_bar_enable_auto_dim_no_visible_wallpaper); mDarkIntensityListeners = new ArrayList(); @@ -127,6 +127,7 @@ public final class NavigationBarTransitions extends BarTransitions implements Display.DEFAULT_DISPLAY); } catch (RemoteException e) { } + mLightTransitionsController.destroy(); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java index abff914693d4..8878c2decb87 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java @@ -85,7 +85,6 @@ import com.android.systemui.shared.rotation.RotationButtonController; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.shared.system.WindowManagerWrapper; -import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.phone.AutoHideController; import com.android.systemui.statusbar.phone.CentralSurfaces; import com.android.systemui.statusbar.phone.LightBarTransitionsController; @@ -140,7 +139,7 @@ public class NavigationBarView extends FrameLayout { private EdgeBackGestureHandler mEdgeBackGestureHandler; private final DeadZone mDeadZone; private boolean mDeadZoneConsuming = false; - private final NavigationBarTransitions mBarTransitions; + private NavigationBarTransitions mBarTransitions; @Nullable private AutoHideController mAutoHideController; @@ -370,7 +369,6 @@ public class NavigationBarView extends FrameLayout { mConfiguration.updateFrom(context.getResources().getConfiguration()); mScreenPinningNotify = new ScreenPinningNotify(mContext); - mBarTransitions = new NavigationBarTransitions(this, Dependency.get(CommandQueue.class)); mButtonDispatchers.put(R.id.back, new ButtonDispatcher(R.id.back)); mButtonDispatchers.put(R.id.home, new ButtonDispatcher(R.id.home)); @@ -418,12 +416,12 @@ public class NavigationBarView extends FrameLayout { } } - public void setAutoHideController(AutoHideController autoHideController) { - mAutoHideController = autoHideController; + void setBarTransitions(NavigationBarTransitions navigationBarTransitions) { + mBarTransitions = navigationBarTransitions; } - public NavigationBarTransitions getBarTransitions() { - return mBarTransitions; + public void setAutoHideController(AutoHideController autoHideController) { + mAutoHideController = autoHideController; } public LightBarTransitionsController getLightTransitionsController() { diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java index cdc6b3b89f0c..363baaa5ef70 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java @@ -264,7 +264,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, mWindowContext = null; } mAutoHideController.setNavigationBar(null); - mLightBarTransitionsController.destroy(mContext); + mLightBarTransitionsController.destroy(); mLightBarController.setNavigationBar(null); mPipOptional.ifPresent(this::removePipExclusionBoundsChangeListener); mInitialized = false; diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java index 097cf3583149..00aa1381ace1 100644 --- a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java +++ b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java @@ -706,7 +706,7 @@ public class PeopleTileViewHelper { Drawable drawable = resolveImage(imageUri, mContext); Bitmap bitmap = convertDrawableToBitmap(drawable); views.setImageViewBitmap(R.id.image, bitmap); - } catch (IOException e) { + } catch (IOException | SecurityException e) { Log.e(TAG, "Could not decode image: " + e); // If we couldn't load the image, show text that we have a new image. views.setTextViewText(R.id.text_content, newImageDescription); @@ -754,7 +754,7 @@ public class PeopleTileViewHelper { return views; } - private Drawable resolveImage(Uri uri, Context context) throws IOException { + Drawable resolveImage(Uri uri, Context context) throws IOException { final ImageDecoder.Source source = ImageDecoder.createSource(context.getContentResolver(), uri); final Drawable drawable = diff --git a/packages/SystemUI/src/com/android/systemui/power/BatteryWarningEvents.java b/packages/SystemUI/src/com/android/systemui/power/BatteryWarningEvents.java new file mode 100644 index 000000000000..1f8a303309d4 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/power/BatteryWarningEvents.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.power; + +import com.android.internal.logging.UiEvent; +import com.android.internal.logging.UiEventLogger; + +/** + * Events related to the battery warning. + */ +public class BatteryWarningEvents { + + /** Enums for logging low battery warning notification and dialog */ + public enum LowBatteryWarningEvent implements UiEventLogger.UiEventEnum { + @UiEvent(doc = "Low battery warning notification displayed") + LOW_BATTERY_NOTIFICATION(1048), + + @UiEvent(doc = "Low battery warning notification positive button clicked") + LOW_BATTERY_NOTIFICATION_TURN_ON(1049), + + @UiEvent(doc = "Low battery warning notification negative button clicked") + LOW_BATTERY_NOTIFICATION_CANCEL(1050), + + @UiEvent(doc = "Low battery warning notification content clicked") + LOW_BATTERY_NOTIFICATION_SETTINGS(1051), + + @UiEvent(doc = "Battery saver confirm dialog displayed") + SAVER_CONFIRM_DIALOG(1052), + + @UiEvent(doc = "Battery saver confirm dialog positive button clicked") + SAVER_CONFIRM_OK(1053), + + @UiEvent(doc = "Battery saver confirm dialog negative button clicked") + SAVER_CONFIRM_CANCEL(1054), + + @UiEvent(doc = "Battery saver confirm dialog dismissed") + SAVER_CONFIRM_DISMISS(1055); + + private final int mId; + + LowBatteryWarningEvent(int id) { + mId = id; + } + + @Override + public int getId() { + return mId; + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java index 3e00a5f74d8f..429f2df6b50c 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java @@ -55,6 +55,7 @@ import android.view.WindowManager; import androidx.annotation.VisibleForTesting; +import com.android.internal.logging.UiEventLogger; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.settingslib.Utils; import com.android.settingslib.fuelgauge.BatterySaverUtils; @@ -169,6 +170,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { private BatteryStateSnapshot mCurrentBatterySnapshot; private ActivityStarter mActivityStarter; private final BroadcastSender mBroadcastSender; + private final UiEventLogger mUiEventLogger; private final Lazy<BatteryController> mBatteryControllerLazy; private final DialogLaunchAnimator mDialogLaunchAnimator; @@ -178,7 +180,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { @Inject public PowerNotificationWarnings(Context context, ActivityStarter activityStarter, BroadcastSender broadcastSender, Lazy<BatteryController> batteryControllerLazy, - DialogLaunchAnimator dialogLaunchAnimator) { + DialogLaunchAnimator dialogLaunchAnimator, UiEventLogger uiEventLogger) { mContext = context; mNoMan = mContext.getSystemService(NotificationManager.class); mPowerMan = (PowerManager) context.getSystemService(Context.POWER_SERVICE); @@ -189,6 +191,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { mBatteryControllerLazy = batteryControllerLazy; mDialogLaunchAnimator = dialogLaunchAnimator; mUseSevereDialog = mContext.getResources().getBoolean(R.bool.config_severe_battery_dialog); + mUiEventLogger = uiEventLogger; } @Override @@ -333,6 +336,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { final Notification n = nb.build(); mNoMan.cancelAsUser(TAG_BATTERY, SystemMessage.NOTE_BAD_CHARGER, UserHandle.ALL); mNoMan.notifyAsUser(TAG_BATTERY, SystemMessage.NOTE_POWER_LOW, n, UserHandle.ALL); + logEvent(BatteryWarningEvents.LowBatteryWarningEvent.LOW_BATTERY_NOTIFICATION); } private boolean showSevereLowBatteryDialog() { @@ -692,17 +696,25 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { } else { d.setTitle(R.string.battery_saver_confirmation_title); d.setPositiveButton(R.string.battery_saver_confirmation_ok, - (dialog, which) -> setSaverMode(true, false)); - d.setNegativeButton(android.R.string.cancel, null); + (dialog, which) -> { + setSaverMode(true, false); + logEvent(BatteryWarningEvents.LowBatteryWarningEvent.SAVER_CONFIRM_OK); + }); + d.setNegativeButton(android.R.string.cancel, (dialog, which) -> + logEvent(BatteryWarningEvents.LowBatteryWarningEvent.SAVER_CONFIRM_CANCEL)); } d.setShowForAllUsers(true); - d.setOnDismissListener((dialog) -> mSaverConfirmation = null); + d.setOnDismissListener((dialog) -> { + mSaverConfirmation = null; + logEvent(BatteryWarningEvents.LowBatteryWarningEvent.SAVER_CONFIRM_DISMISS); + }); WeakReference<View> ref = mBatteryControllerLazy.get().getLastPowerSaverStartView(); if (ref != null && ref.get() != null && ref.get().isAggregatedVisible()) { mDialogLaunchAnimator.showFromView(d, ref.get()); } else { d.show(); } + logEvent(BatteryWarningEvents.LowBatteryWarningEvent.SAVER_CONFIRM_DIALOG); mSaverConfirmation = d; mBatteryControllerLazy.get().clearLastPowerSaverStartView(); } @@ -794,6 +806,12 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { mActivityStarter.startActivity(intent, true /* dismissShade */); } + private void logEvent(BatteryWarningEvents.LowBatteryWarningEvent event) { + if (mUiEventLogger != null) { + mUiEventLogger.log(event); + } + } + private final class Receiver extends BroadcastReceiver { public void init() { @@ -819,15 +837,21 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { final String action = intent.getAction(); Slog.i(TAG, "Received " + action); if (action.equals(ACTION_SHOW_BATTERY_SAVER_SETTINGS)) { + logEvent(BatteryWarningEvents + .LowBatteryWarningEvent.LOW_BATTERY_NOTIFICATION_SETTINGS); dismissLowBatteryNotification(); mContext.startActivityAsUser(mOpenBatterySaverSettings, UserHandle.CURRENT); } else if (action.equals(ACTION_START_SAVER)) { + logEvent(BatteryWarningEvents + .LowBatteryWarningEvent.LOW_BATTERY_NOTIFICATION_TURN_ON); setSaverMode(true, true); dismissLowBatteryNotification(); } else if (action.equals(ACTION_SHOW_START_SAVER_CONFIRMATION)) { dismissLowBatteryNotification(); showStartSaverConfirmation(intent.getExtras()); } else if (action.equals(ACTION_DISMISSED_WARNING)) { + logEvent(BatteryWarningEvents + .LowBatteryWarningEvent.LOW_BATTERY_NOTIFICATION_CANCEL); dismissLowBatteryWarning(); } else if (ACTION_CLICKED_TEMP_WARNING.equals(action)) { dismissHighTemperatureWarningInternal(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt index e63912870a7a..13340b7245fa 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt @@ -228,8 +228,13 @@ class FgsManagerController @Inject constructor( synchronized(lock) { if (dialog == null) { + runningServiceTokens.keys.forEach { + it.updateUiControl() + } + val dialog = SystemUIDialog(context) dialog.setTitle(R.string.fgs_manager_dialog_title) + dialog.setMessage(R.string.fgs_manager_dialog_message) val dialogContext = dialog.context @@ -237,7 +242,9 @@ class FgsManagerController @Inject constructor( recyclerView.layoutManager = LinearLayoutManager(dialogContext) recyclerView.adapter = appListAdapter - dialog.setView(recyclerView) + val topSpacing = dialogContext.resources + .getDimensionPixelSize(R.dimen.fgs_manager_list_top_spacing) + dialog.setView(recyclerView, 0, topSpacing, 0, 0) this.dialog = dialog @@ -396,10 +403,20 @@ class FgsManagerController @Inject constructor( val userId: Int, val packageName: String ) { - val uiControl: UIControl by lazy { - val uid = packageManager.getPackageUidAsUser(packageName, userId) + val uid by lazy { packageManager.getPackageUidAsUser(packageName, userId) } + + private var uiControlInitialized = false + var uiControl: UIControl = UIControl.NORMAL + get() { + if (!uiControlInitialized) { + updateUiControl() + } + return field + } + private set - when (activityManager.getBackgroundRestrictionExemptionReason(uid)) { + fun updateUiControl() { + uiControl = when (activityManager.getBackgroundRestrictionExemptionReason(uid)) { PowerExemptionManager.REASON_SYSTEM_UID, PowerExemptionManager.REASON_DEVICE_DEMO_MODE -> UIControl.HIDE_ENTRY @@ -412,6 +429,7 @@ class FgsManagerController @Inject constructor( PowerExemptionManager.REASON_SYSTEM_MODULE -> UIControl.HIDE_BUTTON else -> UIControl.NORMAL } + uiControlInitialized = true } override fun equals(other: Any?): Boolean { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java index f87f81e40e2c..f87cb29a8758 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java @@ -519,7 +519,10 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca @Override public void setOverScrollAmount(int overScrollAmount) { mOverScrolling = overScrollAmount != 0; - getView().setTranslationY(overScrollAmount); + View view = getView(); + if (view != null) { + view.setTranslationY(overScrollAmount); + } } @Override @@ -609,8 +612,8 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca } else if (progress > 0 && view.getVisibility() != View.VISIBLE) { view.setVisibility((View.VISIBLE)); } - float alpha = mQSPanelController.bouncerInTransit() - ? BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(progress) + float alpha = mQSPanelController.isBouncerInTransit() + ? BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(progress) : ShadeInterpolation.getContentAlpha(progress); view.setAlpha(alpha); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 9fbdd3c873e2..9de132f64d0b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -364,7 +364,7 @@ public class QSPanel extends LinearLayout implements Tunable { setPaddingRelative(getPaddingStart(), paddingTop, getPaddingEnd(), - getPaddingEnd()); + getPaddingBottom()); } 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 5670836566ab..851307ac615f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java @@ -254,8 +254,8 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> { * * @return if bouncer is in transit */ - public boolean bouncerInTransit() { - return mStatusBarKeyguardViewManager.bouncerIsInTransit(); + public boolean isBouncerInTransit() { + return mStatusBarKeyguardViewManager.isBouncerInTransit(); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java index 7e0410c0674b..dd99db49c1d2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java @@ -143,9 +143,10 @@ class QSSecurityFooter extends ViewController<View> @Inject QSSecurityFooter(@Named(QS_SECURITY_FOOTER_VIEW) View rootView, - UserTracker userTracker, @Main Handler mainHandler, ActivityStarter activityStarter, - SecurityController securityController, DialogLaunchAnimator dialogLaunchAnimator, - @Background Looper bgLooper, BroadcastDispatcher broadcastDispatcher) { + UserTracker userTracker, @Main Handler mainHandler, + ActivityStarter activityStarter, SecurityController securityController, + DialogLaunchAnimator dialogLaunchAnimator, @Background Looper bgLooper, + BroadcastDispatcher broadcastDispatcher) { super(rootView); mFooterText = mView.findViewById(R.id.footer_text); mPrimaryFooterIcon = mView.findViewById(R.id.primary_footer_icon); @@ -493,21 +494,23 @@ class QSSecurityFooter extends ViewController<View> private void createDialog() { mShouldUseSettingsButton.set(false); - final View view = createDialogView(); - mMainHandler.post(() -> { - mDialog = new SystemUIDialog(mContext, 0); // Use mContext theme - mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE); - mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(), this); - mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, - mShouldUseSettingsButton.get() ? getSettingsButton() : getNegativeButton(), - this); - - mDialog.setView(view); - if (mView.isAggregatedVisible()) { - mDialogLaunchAnimator.showFromView(mDialog, mView); - } else { - mDialog.show(); - } + mHandler.post(() -> { + String settingsButtonText = getSettingsButton(); + final View view = createDialogView(); + mMainHandler.post(() -> { + mDialog = new SystemUIDialog(mContext, 0); // Use mContext theme + mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(), this); + mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, mShouldUseSettingsButton.get() + ? settingsButtonText : getNegativeButton(), this); + + mDialog.setView(view); + if (mView.isAggregatedVisible()) { + mDialogLaunchAnimator.showFromView(mDialog, mView); + } else { + mDialog.show(); + } + }); }); } @@ -650,6 +653,7 @@ class QSSecurityFooter extends ViewController<View> } } + // This should not be called on the main thread to avoid making an IPC. @VisibleForTesting String getSettingsButton() { return mDpm.getResources().getString( diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java index 3c95da873273..112b1e827845 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java @@ -71,7 +71,11 @@ public class QuickQSPanel extends QSPanel { @Override protected void updatePadding() { - // QS Panel is setting a top padding by default, which we don't need. + int bottomPadding = getResources().getDimensionPixelSize(R.dimen.qqs_layout_padding_bottom); + setPaddingRelative(getPaddingStart(), + getPaddingTop(), + getPaddingEnd(), + bottomPadding); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsController.java b/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsController.java index 42d603ec5051..39d081da43cb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsController.java @@ -26,6 +26,7 @@ import android.provider.Settings; import androidx.annotation.NonNull; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.policy.CallbackController; @@ -38,6 +39,7 @@ import javax.inject.Inject; /** * @hide */ +@SysUISingleton public class ReduceBrightColorsController implements CallbackController<ReduceBrightColorsController.Listener> { private final ColorDisplayManager mManager; diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java index 5d4b3da58cf0..628964af3380 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java +++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java @@ -35,6 +35,7 @@ import com.android.systemui.statusbar.policy.CastController; import com.android.systemui.statusbar.policy.DataSaverController; import com.android.systemui.statusbar.policy.DeviceControlsController; import com.android.systemui.statusbar.policy.HotspotController; +import com.android.systemui.statusbar.policy.SafetyController; import com.android.systemui.statusbar.policy.WalletController; import com.android.systemui.util.settings.SecureSettings; @@ -66,6 +67,7 @@ public interface QSModule { ReduceBrightColorsController reduceBrightColorsController, DeviceControlsController deviceControlsController, WalletController walletController, + SafetyController safetyController, @Named(RBC_AVAILABLE) boolean isReduceBrightColorsAvailable) { AutoTileManager manager = new AutoTileManager( context, @@ -81,6 +83,7 @@ public interface QSModule { reduceBrightColorsController, deviceControlsController, walletController, + safetyController, isReduceBrightColorsAvailable ); manager.init(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java index 8921e95fcee9..8ca095d9a609 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java @@ -58,6 +58,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.android.internal.logging.UiEvent; import com.android.internal.logging.UiEventLogger; import com.android.settingslib.Utils; +import com.android.settingslib.wifi.WifiEnterpriseRestrictionUtils; import com.android.systemui.Prefs; import com.android.systemui.R; import com.android.systemui.accessibility.floatingmenu.AnnotationLinkSpan; @@ -136,6 +137,7 @@ public class InternetDialog extends SystemUIDialog implements private Drawable mBackgroundOff = null; private int mDefaultDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; private boolean mCanConfigMobileData; + private boolean mCanChangeWifiState; // Wi-Fi entries private int mWifiNetworkHeight; @@ -180,6 +182,7 @@ public class InternetDialog extends SystemUIDialog implements mWifiManager = mInternetDialogController.getWifiManager(); mCanConfigMobileData = canConfigMobileData; mCanConfigWifi = canConfigWifi; + mCanChangeWifiState = WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(context); mKeyguard = keyguardStateController; mUiEventLogger = uiEventLogger; @@ -449,6 +452,14 @@ public class InternetDialog extends SystemUIDialog implements } mTurnWifiOnLayout.setBackground( (isDeviceLocked && mConnectedWifiEntry != null) ? mBackgroundOn : null); + + if (!mCanChangeWifiState && mWiFiToggle.isEnabled()) { + mWiFiToggle.setEnabled(false); + mWifiToggleTitleText.setEnabled(false); + final TextView summaryText = mDialogView.requireViewById(R.id.wifi_toggle_summary); + summaryText.setEnabled(false); + summaryText.setVisibility(View.VISIBLE); + } } @MainThread diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index 61f49e044b99..551e8b51ae11 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -502,8 +502,8 @@ public class KeyguardIndicationController { private void updateLockScreenTrustMsg(int userId, CharSequence trustGrantedIndication, CharSequence trustManagedIndication) { - if (!TextUtils.isEmpty(trustGrantedIndication) - && mKeyguardUpdateMonitor.getUserHasTrust(userId)) { + final boolean userHasTrust = mKeyguardUpdateMonitor.getUserHasTrust(userId); + if (!TextUtils.isEmpty(trustGrantedIndication) && userHasTrust) { mRotateTextViewController.updateIndication( INDICATION_TYPE_TRUST, new KeyguardIndication.Builder() @@ -513,7 +513,7 @@ public class KeyguardIndicationController { false); } else if (!TextUtils.isEmpty(trustManagedIndication) && mKeyguardUpdateMonitor.getUserTrustIsManaged(userId) - && !mKeyguardUpdateMonitor.getUserHasTrust(userId)) { + && !userHasTrust) { mRotateTextViewController.updateIndication( INDICATION_TYPE_TRUST, new KeyguardIndication.Builder() @@ -896,21 +896,8 @@ public class KeyguardIndicationController { } } - private void showTryFingerprintMsg(int msgId, String a11yString) { - if (mKeyguardUpdateMonitor.isUdfpsSupported()) { - // if udfps available, there will always be a tappable affordance to unlock - // For example, the lock icon - if (mKeyguardBypassController.getUserHasDeviceEntryIntent()) { - showBiometricMessage(R.string.keyguard_unlock_press); - } else if (msgId == FaceManager.FACE_ERROR_LOCKOUT_PERMANENT) { - // since face is locked out, simply show "try fingerprint" - showBiometricMessage(R.string.keyguard_try_fingerprint); - } else { - showBiometricMessage(R.string.keyguard_face_failed_use_fp); - } - } else { - showBiometricMessage(R.string.keyguard_try_fingerprint); - } + private void showFaceFailedTryFingerprintMsg(int msgId, String a11yString) { + showBiometricMessage(R.string.keyguard_face_failed_use_fp); // Although we suppress face auth errors visually, we still announce them for a11y if (!TextUtils.isEmpty(a11yString)) { @@ -1002,7 +989,7 @@ public class KeyguardIndicationController { } else if (mScreenLifecycle.getScreenState() == SCREEN_ON) { if (biometricSourceType == BiometricSourceType.FACE && shouldSuppressFaceMsgAndShowTryFingerprintMsg()) { - showTryFingerprintMsg(msgId, helpString); + showFaceFailedTryFingerprintMsg(msgId, helpString); return; } showBiometricMessage(helpString); @@ -1022,7 +1009,7 @@ public class KeyguardIndicationController { && shouldSuppressFaceMsgAndShowTryFingerprintMsg() && !mStatusBarKeyguardViewManager.isBouncerShowing() && mScreenLifecycle.getScreenState() == SCREEN_ON) { - showTryFingerprintMsg(msgId, errString); + showFaceFailedTryFingerprintMsg(msgId, errString); return; } if (msgId == FaceManager.FACE_ERROR_TIMEOUT) { @@ -1031,10 +1018,10 @@ public class KeyguardIndicationController { if (!mStatusBarKeyguardViewManager.isBouncerShowing() && mKeyguardUpdateMonitor.isUdfpsEnrolled() && mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) { - showTryFingerprintMsg(msgId, errString); + showFaceFailedTryFingerprintMsg(msgId, errString); } else if (mStatusBarKeyguardViewManager.isShowingAlternateAuth()) { mStatusBarKeyguardViewManager.showBouncerMessage( - mContext.getResources().getString(R.string.keyguard_unlock_press), + mContext.getResources().getString(R.string.keyguard_try_fingerprint), mInitialTextColorState ); } else { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt index 9a932bae833e..270bdc785178 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt @@ -11,6 +11,7 @@ import android.graphics.PorterDuffColorFilter import android.graphics.PorterDuffXfermode import android.graphics.RadialGradient import android.graphics.Shader +import android.os.Trace import android.util.AttributeSet import android.util.MathUtils.lerp import android.view.View @@ -222,6 +223,8 @@ class LightRevealScrim(context: Context?, attrs: AttributeSet?) : View(context, revealEffect.setRevealAmountOnScrim(value, this) updateScrimOpaque() + Trace.traceCounter(Trace.TRACE_TAG_APP, "light_reveal_amount", + (field * 100).toInt()) invalidate() } } @@ -355,8 +358,8 @@ class LightRevealScrim(context: Context?, attrs: AttributeSet?) : View(context, } override fun onDraw(canvas: Canvas?) { - if (canvas == null || revealGradientWidth <= 0 || revealGradientHeight <= 0 - || revealAmount == 0f) { + if (canvas == null || revealGradientWidth <= 0 || revealGradientHeight <= 0 || + revealAmount == 0f) { if (revealAmount < 1f) { canvas?.drawColor(revealGradientEndColor) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt index f15df8ec2816..c1ea6bf7cec8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt @@ -72,6 +72,9 @@ class LockscreenShadeTransitionController @Inject constructor( dumpManager: DumpManager ) : Dumpable { private var pulseHeight: Float = 0f + @get:VisibleForTesting + var fractionToShade: Float = 0f + private set private var useSplitShade: Boolean = false private lateinit var nsslController: NotificationStackScrollLayoutController lateinit var notificationPanelController: NotificationPanelViewController @@ -405,9 +408,9 @@ class LockscreenShadeTransitionController @Inject constructor( if (field != value || forceApplyAmount) { field = value if (!nsslController.isInLockedDownShade() || field == 0f || forceApplyAmount) { - val notificationShelfProgress = + fractionToShade = MathUtils.saturate(dragDownAmount / notificationShelfTransitionDistance) - nsslController.setTransitionToFullShadeAmount(notificationShelfProgress) + nsslController.setTransitionToFullShadeAmount(fractionToShade) qSDragProgress = MathUtils.saturate(dragDownAmount / qsTransitionDistance) qS.setTransitionToFullShadeAmount(field, qSDragProgress) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java index 241a745b92e2..76f9db44af66 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java @@ -454,7 +454,7 @@ public class NotificationMediaManager implements Dumpable { * update this manager's internal state. * @return whether the current MediaMetadata changed (and needs to be announced to listeners). */ - private boolean findPlayingMediaNotification( + boolean findPlayingMediaNotification( @NonNull Collection<NotificationEntry> allNotifications) { boolean metaDataChanged = false; // Promote the media notification with a controller in 'playing' state, if any. @@ -465,7 +465,7 @@ public class NotificationMediaManager implements Dumpable { if (notif.isMediaNotification()) { final MediaSession.Token token = entry.getSbn().getNotification().extras.getParcelable( - Notification.EXTRA_MEDIA_SESSION); + Notification.EXTRA_MEDIA_SESSION, MediaSession.Token.class); if (token != null) { MediaController aController = new MediaController(mContext, token); if (PlaybackState.STATE_PLAYING diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index 633786ffa787..afce945a5bc5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -85,9 +85,6 @@ public class NotificationShelf extends ActivatableNotificationView implements private NotificationShelfController mController; private float mActualWidth = -1; - /** Fraction of lockscreen to shade animation (on lockscreen swipe down). */ - private float mFractionToShade; - public NotificationShelf(Context context, AttributeSet attrs) { super(context, attrs); } @@ -234,13 +231,6 @@ public class NotificationShelf extends ActivatableNotificationView implements } /** - * @param fractionToShade Fraction of lockscreen to shade transition - */ - public void setFractionToShade(float fractionToShade) { - mFractionToShade = fractionToShade; - } - - /** * @return Actual width of shelf, accounting for possible ongoing width animation */ public int getActualWidth() { @@ -411,7 +401,8 @@ public class NotificationShelf extends ActivatableNotificationView implements || !mShowNotificationShelf || numViewsInShelf < 1f; - final float fractionToShade = Interpolators.STANDARD.getInterpolation(mFractionToShade); + final float fractionToShade = Interpolators.STANDARD.getInterpolation( + mAmbientState.getFractionToShade()); final float shortestWidth = mShelfIcons.calculateWidthFor(numViewsInShelf); updateActualWidth(fractionToShade, shortestWidth); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index 0fb6ea669458..039a3625c70c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java @@ -573,11 +573,10 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi } catch (RuntimeException e) { Log.e(TAG, "Unable to recover builder", e); // Trying to get the app name from the app info instead. - Parcelable appInfo = n.extras.getParcelable( - Notification.EXTRA_BUILDER_APPLICATION_INFO); - if (appInfo instanceof ApplicationInfo) { - appName = String.valueOf(((ApplicationInfo) appInfo).loadLabel( - c.getPackageManager())); + ApplicationInfo appInfo = n.extras.getParcelable( + Notification.EXTRA_BUILDER_APPLICATION_INFO, ApplicationInfo.class); + if (appInfo != null) { + appName = String.valueOf(appInfo.loadLabel(c.getPackageManager())); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java index 0fd9272c7da7..4fc347a09292 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java @@ -542,7 +542,8 @@ public final class NotificationEntry extends ListEntry { if (senderPerson == null) { return true; } - Person user = extras.getParcelable(Notification.EXTRA_MESSAGING_PERSON); + Person user = extras.getParcelable( + Notification.EXTRA_MESSAGING_PERSON, Person.class); return Objects.equals(user, senderPerson); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index 5bf75c796fc9..7245cb246932 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -32,6 +32,7 @@ import android.annotation.Nullable; import android.app.INotificationManager; import android.app.Notification; import android.app.NotificationChannel; +import android.app.role.RoleManager; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -380,12 +381,22 @@ public class ExpandableNotificationRow extends ActivatableNotificationView Settings.Secure.NOTIFICATION_PERMISSION_ENABLED, 0, USER_SYSTEM) == 1) { INotificationManager iNm = INotificationManager.Stub.asInterface( ServiceManager.getService(Context.NOTIFICATION_SERVICE)); + + boolean isSystem = false; try { - return iNm.isPermissionFixed(sbn.getPackageName(), sbn.getUserId()); + isSystem = iNm.isPermissionFixed(sbn.getPackageName(), sbn.getUserId()); } catch (RemoteException e) { Log.e(TAG, "cannot reach NMS"); } - return false; + RoleManager rm = context.getSystemService(RoleManager.class); + List<String> fixedRoleHolders = new ArrayList<>(); + fixedRoleHolders.addAll(rm.getRoleHolders(RoleManager.ROLE_DIALER)); + fixedRoleHolders.addAll(rm.getRoleHolders(RoleManager.ROLE_EMERGENCY)); + if (fixedRoleHolders.contains(sbn.getPackageName())) { + isSystem = true; + } + + return isSystem; } else { PackageManager packageManager = CentralSurfaces.getPackageManagerForUser( context, sbn.getUser().getIdentifier()); @@ -2647,9 +2658,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView return; } - // bail out if no public version - if (mPublicLayout.getChildCount() == 0) return; - if (!animated) { mPublicLayout.animate().cancel(); mPrivateLayout.animate().cancel(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java index 59a78ed6f4ea..8b01a4790f3c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java @@ -124,6 +124,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G private NotificationEntry mEntry; private StatusBarNotification mSbn; private boolean mIsDeviceProvisioned; + private boolean mIsSystemRegisteredCall; private OnSettingsClickListener mOnSettingsClickListener; private OnAppSettingsClickListener mAppSettingsClickListener; @@ -229,6 +230,9 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G mShowAutomaticSetting = mAssistantFeedbackController.isFeedbackEnabled(); mUiEventLogger = uiEventLogger; + mIsSystemRegisteredCall = mSbn.getNotification().isStyle(Notification.CallStyle.class) + && mINotificationManager.isInCall(mSbn.getPackageName(), mSbn.getUid()); + int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage( pkg, mAppUid, false /* includeDeleted */); if (mNumUniqueChannelsInRow == 0) { @@ -252,17 +256,27 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G } private void bindInlineControls() { - if (mIsNonblockable) { + if (mIsSystemRegisteredCall) { + findViewById(R.id.non_configurable_call_text).setVisibility(VISIBLE); + findViewById(R.id.non_configurable_text).setVisibility(GONE); + findViewById(R.id.non_configurable_multichannel_text).setVisibility(GONE); + findViewById(R.id.interruptiveness_settings).setVisibility(GONE); + ((TextView) findViewById(R.id.done)).setText(R.string.inline_done_button); + findViewById(R.id.turn_off_notifications).setVisibility(GONE); + } else if (mIsNonblockable) { findViewById(R.id.non_configurable_text).setVisibility(VISIBLE); + findViewById(R.id.non_configurable_call_text).setVisibility(GONE); findViewById(R.id.non_configurable_multichannel_text).setVisibility(GONE); findViewById(R.id.interruptiveness_settings).setVisibility(GONE); ((TextView) findViewById(R.id.done)).setText(R.string.inline_done_button); findViewById(R.id.turn_off_notifications).setVisibility(GONE); } else if (mNumUniqueChannelsInRow > 1) { + findViewById(R.id.non_configurable_call_text).setVisibility(GONE); findViewById(R.id.non_configurable_text).setVisibility(GONE); findViewById(R.id.interruptiveness_settings).setVisibility(GONE); findViewById(R.id.non_configurable_multichannel_text).setVisibility(VISIBLE); } else { + findViewById(R.id.non_configurable_call_text).setVisibility(GONE); findViewById(R.id.non_configurable_text).setVisibility(GONE); findViewById(R.id.non_configurable_multichannel_text).setVisibility(GONE); findViewById(R.id.interruptiveness_settings).setVisibility(VISIBLE); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapper.java index 79f99b85c410..8732696dc7a1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapper.java @@ -44,9 +44,8 @@ public class NotificationBigPictureTemplateViewWrapper extends NotificationTempl private void updateImageTag(StatusBarNotification sbn) { final Bundle extras = sbn.getNotification().extras; - boolean bigLargeIconSet = extras.containsKey(Notification.EXTRA_LARGE_ICON_BIG); - if (bigLargeIconSet) { - Icon bigLargeIcon = extras.getParcelable(Notification.EXTRA_LARGE_ICON_BIG); + Icon bigLargeIcon = extras.getParcelable(Notification.EXTRA_LARGE_ICON_BIG, Icon.class); + if (bigLargeIcon != null) { mRightIcon.setTag(ImageTransformState.ICON_TAG, bigLargeIcon); mLeftIcon.setTag(ImageTransformState.ICON_TAG, bigLargeIcon); } else { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java index 2f1022a904e8..9acd60eb862a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java @@ -31,6 +31,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.notification.row.ExpandableView; import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.BypassController; import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.SectionProvider; +import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import javax.inject.Inject; @@ -45,6 +46,10 @@ public class AmbientState { private final SectionProvider mSectionProvider; private final BypassController mBypassController; + /** + * Used to read bouncer states. + */ + private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private int mScrollY; private boolean mDimmed; private ActivatableNotificationView mActivatedChild; @@ -77,6 +82,23 @@ public class AmbientState { private boolean mAppearing; private float mPulseHeight = MAX_PULSE_HEIGHT; + /** Fraction of lockscreen to shade animation (on lockscreen swipe down). */ + private float mFractionToShade; + + /** + * @param fractionToShade Fraction of lockscreen to shade transition + */ + public void setFractionToShade(float fractionToShade) { + mFractionToShade = fractionToShade; + } + + /** + * @return fractionToShade Fraction of lockscreen to shade transition + */ + public float getFractionToShade() { + return mFractionToShade; + } + /** How we much we are sleeping. 1f fully dozing (AOD), 0f fully awake (for all other states) */ private float mDozeAmount = 0.0f; @@ -204,9 +226,11 @@ public class AmbientState { public AmbientState( Context context, @NonNull SectionProvider sectionProvider, - @NonNull BypassController bypassController) { + @NonNull BypassController bypassController, + @Nullable StatusBarKeyguardViewManager statusBarKeyguardViewManager) { mSectionProvider = sectionProvider; mBypassController = bypassController; + mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; reload(context); } @@ -661,4 +685,14 @@ public class AmbientState { public int getStackTopMargin() { return mStackTopMargin; } + + /** + * Check to see if we are about to show bouncer. + * + * @return if bouncer expansion is between 0 and 1. + */ + public boolean isBouncerInTransit() { + return mStatusBarKeyguardViewManager != null + && mStatusBarKeyguardViewManager.isBouncerInTransit(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 15a93c871c80..851794c0440e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -417,7 +417,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private NotificationShelf mShelf; private int mMaxDisplayedNotifications = -1; private float mKeyguardBottomPadding = -1; - private float mKeyguardNotificationAvailableSpace = -1; @VisibleForTesting int mStatusBarHeight; private int mMinInteractionHeight; private final Rect mClipRect = new Rect(); @@ -775,9 +774,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable y = (int) mMaxLayoutHeight; drawDebugInfo(canvas, y, Color.MAGENTA, /* label= */ "mMaxLayoutHeight = " + y); + // The space between mTopPadding and mKeyguardBottomPadding determines the available space + // for notifications on keyguard. if (mKeyguardBottomPadding >= 0) { y = getHeight() - (int) mKeyguardBottomPadding; - drawDebugInfo(canvas, y, Color.GRAY, + drawDebugInfo(canvas, y, Color.RED, /* label= */ "getHeight() - mKeyguardBottomPadding = " + y); } @@ -789,7 +790,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable drawDebugInfo(canvas, y, Color.CYAN, /* label= */ "mAmbientState.getStackY() = " + y); y = (int) (mAmbientState.getStackY() + mAmbientState.getStackHeight()); - drawDebugInfo(canvas, y, Color.BLUE, + drawDebugInfo(canvas, y, Color.LTGRAY, /* label= */ "mAmbientState.getStackY() + mAmbientState.getStackHeight() = " + y); y = (int) mAmbientState.getStackY() + mContentHeight; @@ -800,10 +801,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable drawDebugInfo(canvas, y, Color.YELLOW, /* label= */ "mAmbientState.getStackY() + mIntrinsicContentHeight = " + y); - y = (int) (mAmbientState.getStackY() + mKeyguardNotificationAvailableSpace); - drawDebugInfo(canvas, y, Color.RED, /* label= */ - "mAmbientState.getStackY() + mKeyguardNotificationAvailableSpace = " + y); - drawDebugInfo(canvas, mRoundedRectClippingBottom, Color.DKGRAY, /* label= */ "mRoundedRectClippingBottom) = " + y); } @@ -2267,10 +2264,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) private void updateContentHeight() { final float scrimTopPadding = mAmbientState.isOnKeyguard() ? 0 : mMinimumPaddings; + final int shelfIntrinsicHeight = mShelf != null ? mShelf.getIntrinsicHeight() : 0; final int height = (int) scrimTopPadding + (int) mNotificationStackSizeCalculator.computeHeight( /* notificationStackScrollLayout= */ this, mMaxDisplayedNotifications, - mShelf != null ? mShelf.getIntrinsicHeight() : 0); + shelfIntrinsicHeight); mIntrinsicContentHeight = height; // The topPadding can be bigger than the regular padding when qs is expanded, in that @@ -2297,7 +2295,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable int visibleIndex ) { return mStackScrollAlgorithm.getGapHeightForChild(mSectionsManager, visibleIndex, current, - previous); + previous, mAmbientState.getFractionToShade(), mAmbientState.isOnKeyguard()); } @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) @@ -4914,15 +4912,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mKeyguardBottomPadding = keyguardBottomPadding; } - /** - * For debugging only. Enables to draw a line related to the available size for notifications in - * keyguard. - */ - public void setKeyguardAvailableSpaceForDebug(float keyguardNotificationAvailableSpace) { - mKeyguardNotificationAvailableSpace = keyguardNotificationAvailableSpace; - } - - @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) public void setShouldShowShelfOnly(boolean shouldShowShelfOnly) { mShouldShowShelfOnly = shouldShowShelfOnly; @@ -5512,7 +5501,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable * where it remains until the next lockscreen-to-shade transition. */ public void setFractionToShade(float fraction) { - mShelf.setFractionToShade(fraction); + mAmbientState.setFractionToShade(fraction); requestChildrenUpdate(); } 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 440bea638231..ea6987a62e52 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 @@ -1305,12 +1305,6 @@ public class NotificationStackScrollLayoutController { mView.setKeyguardBottomPadding(keyguardBottomPadding); } - /** For debugging only. */ - public void mKeyguardNotificationAvailableSpaceForDebug( - float keyguardNotificationAvailableSpace) { - mView.setKeyguardAvailableSpaceForDebug(keyguardNotificationAvailableSpace); - } - public RemoteInputController.Delegate createDelegate() { return new RemoteInputController.Delegate() { public void setRemoteInputActive(NotificationEntry entry, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt index 7fb115d21fa5..2b11f693da1d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt @@ -19,9 +19,11 @@ package com.android.systemui.statusbar.notification.stack import android.content.res.Resources import android.util.Log import android.view.View.GONE +import androidx.annotation.VisibleForTesting import com.android.systemui.R import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.statusbar.LockscreenShadeTransitionController import com.android.systemui.statusbar.StatusBarState.KEYGUARD import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow @@ -29,6 +31,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableView import com.android.systemui.util.children import javax.inject.Inject import kotlin.math.max +import kotlin.math.min import kotlin.properties.Delegates.notNull private const val TAG = "NotificationStackSizeCalculator" @@ -40,6 +43,7 @@ class NotificationStackSizeCalculator @Inject constructor( private val statusBarStateController: SysuiStatusBarStateController, + private val lockscreenShadeTransitionController: LockscreenShadeTransitionController, @Main private val resources: Resources ) { @@ -51,9 +55,7 @@ constructor( */ private var maxKeyguardNotifications by notNull<Int>() - /** - * Minimum space between two notifications, see [calculateGapAndDividerHeight]. - */ + /** Minimum space between two notifications, see [calculateGapAndDividerHeight]. */ private var dividerHeight by notNull<Int>() init { @@ -61,55 +63,34 @@ constructor( } /** - * Given the [availableSpace] constraint, calculates how many notification to show. + * Given the [totalAvailableSpace] constraint, calculates how many notification to show. * * This number is only valid in keyguard. * - * @param availableSpace space for notifications. This doesn't include the space for the shelf. + * @param totalAvailableSpace space for notifications. This includes the space for the shelf. */ fun computeMaxKeyguardNotifications( stack: NotificationStackScrollLayout, - availableSpace: Float, - shelfHeight: Float + totalAvailableSpace: Float, + shelfIntrinsicHeight: Float ): Int { - log { - "computeMaxKeyguardNotifications(" + - "availableSpace=$availableSpace shelfHeight=$shelfHeight)" + val stackHeightSequence = computeHeightPerNotificationLimit(stack, shelfIntrinsicHeight) + + var maxNotifications = + stackHeightSequence.lastIndexWhile { stackHeight -> stackHeight <= totalAvailableSpace } + + if (onLockscreen()) { + maxNotifications = min(maxKeyguardNotifications, maxNotifications) } - val children: Sequence<ExpandableView> = stack.childrenSequence - var remainingSpace: Float = availableSpace - var count = 0 - var previous: ExpandableView? = null - val onLockscreen = true - val showableRows = children.filter { it.isShowable(onLockscreen) } - val showableRowsCount = showableRows.count() - log { "\tshowableRowsCount=$showableRowsCount "} - - showableRows.forEachIndexed { i, current -> - val spaceNeeded = current.spaceNeeded(count, previous, stack, onLockscreen) - val spaceAfter = remainingSpace - spaceNeeded - previous = current - log { "\ti=$i spaceNeeded=$spaceNeeded remainingSpace=$remainingSpace " + - "spaceAfter=$spaceAfter" } - - if (remainingSpace - spaceNeeded >= 0 && count < maxKeyguardNotifications) { - count += 1 - remainingSpace -= spaceNeeded - } else if (remainingSpace - spaceNeeded > -shelfHeight && i == showableRowsCount - 1) { - log { "Show all notifications. Shelf not needed." } - // If this is the last one, and it fits using the space shelf would use, then we can - // display it, as the shelf will not be needed (as all notifications are shown). - return count + 1 - } else { - log { - "No more fit. Returning $count. Space used: ${availableSpace - remainingSpace}" - } - return count - } + // Could be < 0 if the space available is less than the shelf size. Returns 0 in this case. + maxNotifications = max(0, maxNotifications) + log { + "computeMaxKeyguardNotifications(" + + "availableSpace=$totalAvailableSpace" + + " shelfHeight=$shelfIntrinsicHeight) -> $maxNotifications" } - log { "All fit. Returning $count" } - return count + return maxNotifications } /** @@ -119,68 +100,87 @@ constructor( * @param stack stack containing notifications as children. * @param maxNotifications Maximum number of notifications. When reached, the others will go * into the shelf. - * @param shelfHeight height of the shelf. It might be zero. + * @param shelfIntrinsicHeight height of the shelf, without any padding. It might be zero. * * @return height of the stack, including shelf height, if needed. */ fun computeHeight( stack: NotificationStackScrollLayout, maxNotifications: Int, - shelfHeight: Float + shelfIntrinsicHeight: Float ): Float { - val children: Sequence<ExpandableView> = stack.childrenSequence - val maxNotificationsArg = infiniteIfNegative(maxNotifications) + val heightPerMaxNotifications = + computeHeightPerNotificationLimit(stack, shelfIntrinsicHeight) + val height = + heightPerMaxNotifications.elementAtOrElse(maxNotifications) { + heightPerMaxNotifications.last() // Height with all notifications visible. + } + log { "computeHeight(maxNotifications=$maxNotifications) -> $height" } + return height + } + + /** The ith result in the sequence is the height with ith max notifications. */ + private fun computeHeightPerNotificationLimit( + stack: NotificationStackScrollLayout, + shelfIntrinsicHeight: Float + ): Sequence<Float> = sequence { + val children = stack.showableChildren().toList() var height = 0f var previous: ExpandableView? = null - var count = 0 val onLockscreen = onLockscreen() - log { "computeHeight(maxNotification=$maxNotifications, shelf=$shelfHeight" } - children.filter { it.isShowable(onLockscreen) }.forEach { current -> - if (count < maxNotificationsArg) { - val spaceNeeded = current.spaceNeeded(count, previous, stack, onLockscreen) - log { "\ti=$count spaceNeeded=$spaceNeeded" } - height += spaceNeeded - count += 1 - } else { - height += current.calculateGapAndDividerHeight(stack, previous, count) - height += shelfHeight - log { "returning height with shelf -> $height" } - return height - } - previous = current + yield(dividerHeight + shelfIntrinsicHeight) // Only shelf. + + children.forEachIndexed { i, currentNotification -> + height += spaceNeeded(currentNotification, i, previous, stack, onLockscreen) + previous = currentNotification + + val shelfHeight = + if (i == children.lastIndex) { + 0f // No shelf needed. + } else { + val spaceBeforeShelf = + calculateGapAndDividerHeight( + stack, previous = currentNotification, current = children[i + 1], i) + spaceBeforeShelf + shelfIntrinsicHeight + } + + yield(height + shelfHeight) } - log { "Returning height without shelf -> $height" } - return height } fun updateResources() { maxKeyguardNotifications = infiniteIfNegative(resources.getInteger(R.integer.keyguard_max_notification_count)) - dividerHeight = - max(1, resources.getDimensionPixelSize(R.dimen.notification_divider_height)) + dividerHeight = max(1, resources.getDimensionPixelSize(R.dimen.notification_divider_height)) } private val NotificationStackScrollLayout.childrenSequence: Sequence<ExpandableView> get() = children.map { it as ExpandableView } - private fun onLockscreen() = statusBarStateController.state == KEYGUARD + @VisibleForTesting + fun onLockscreen() : Boolean { + return statusBarStateController.state == KEYGUARD + && lockscreenShadeTransitionController.fractionToShade == 0f + } - private fun ExpandableView.spaceNeeded( + @VisibleForTesting + fun spaceNeeded( + view: ExpandableView, visibleIndex: Int, previousView: ExpandableView?, stack: NotificationStackScrollLayout, onLockscreen: Boolean ): Float { - assert(isShowable(onLockscreen)) + assert(view.isShowable(onLockscreen)) var size = if (onLockscreen) { - getMinHeight(/* ignoreTemporaryStates= */ true).toFloat() + view.getMinHeight(/* ignoreTemporaryStates= */ true).toFloat() } else { - intrinsicHeight.toFloat() + view.intrinsicHeight.toFloat() } - size += calculateGapAndDividerHeight(stack, previousView, visibleIndex) + size += calculateGapAndDividerHeight(stack, previousView, current = view, visibleIndex) return size } @@ -200,18 +200,22 @@ constructor( return true } - private fun ExpandableView.calculateGapAndDividerHeight( + private fun calculateGapAndDividerHeight( stack: NotificationStackScrollLayout, previous: ExpandableView?, + current: ExpandableView?, visibleIndex: Int - ) : Float { - var height = stack.calculateGapHeight(previous, /* current= */ this, visibleIndex) + ): Float { + var height = stack.calculateGapHeight(previous, current, visibleIndex) if (visibleIndex != 0) { height += dividerHeight } return height } + private fun NotificationStackScrollLayout.showableChildren() = + this.childrenSequence.filter { it.isShowable(onLockscreen()) } + /** * Can a view be shown on the lockscreen when calculating the number of allowed notifications to * show? @@ -240,4 +244,8 @@ constructor( } else { v } + + /** Returns the last index where [predicate] returns true, or -1 if it was always false. */ + private fun <T> Sequence<T>.lastIndexWhile(predicate: (T) -> Boolean): Int = + takeWhile(predicate).count() - 1 } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java index c0971337a19f..22242b8fb4b4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java @@ -27,6 +27,7 @@ import android.view.ViewGroup; import androidx.annotation.VisibleForTesting; import com.android.internal.policy.SystemBarUtils; +import com.android.keyguard.BouncerPanelExpansionCalculator; import com.android.systemui.R; import com.android.systemui.animation.ShadeInterpolation; import com.android.systemui.statusbar.EmptyShadeView; @@ -53,6 +54,7 @@ public class StackScrollAlgorithm { private int mPaddingBetweenElements; private int mGapHeight; + private int mGapHeightOnLockscreen; private int mCollapsedSize; private StackScrollAlgorithmState mTempAlgorithmState = new StackScrollAlgorithmState(); @@ -86,6 +88,8 @@ public class StackScrollAlgorithm { mPinnedZTranslationExtra = res.getDimensionPixelSize( R.dimen.heads_up_pinned_elevation); mGapHeight = res.getDimensionPixelSize(R.dimen.notification_section_divider_height); + mGapHeightOnLockscreen = res.getDimensionPixelSize( + R.dimen.notification_section_divider_height_lockscreen); mNotificationScrimPadding = res.getDimensionPixelSize(R.dimen.notification_side_paddings); mMarginBottom = res.getDimensionPixelSize(R.dimen.notification_panel_margin_bottom); } @@ -304,7 +308,8 @@ public class StackScrollAlgorithm { ambientState.getSectionProvider(), i, view, getPreviousView(i, state)); if (applyGapHeight) { - currentY += mGapHeight; + currentY += getGapForLocation( + ambientState.getFractionToShade(), ambientState.isOnKeyguard()); } if (ambientState.getShelf() != null) { @@ -431,7 +436,9 @@ public class StackScrollAlgorithm { } else if (ambientState.isExpansionChanging()) { // Adjust alpha for shade open & close. float expansion = ambientState.getExpansionFraction(); - viewState.alpha = ShadeInterpolation.getContentAlpha(expansion); + viewState.alpha = ambientState.isBouncerInTransit() + ? BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion) + : ShadeInterpolation.getContentAlpha(expansion); } if (ambientState.isShadeExpanded() && view.mustStayOnScreen() @@ -451,8 +458,10 @@ public class StackScrollAlgorithm { ambientState.getSectionProvider(), i, view, getPreviousView(i, algorithmState)); if (applyGapHeight) { - algorithmState.mCurrentYPosition += expansionFraction * mGapHeight; - algorithmState.mCurrentExpandedYPosition += mGapHeight; + final float gap = getGapForLocation( + ambientState.getFractionToShade(), ambientState.isOnKeyguard()); + algorithmState.mCurrentYPosition += expansionFraction * gap; + algorithmState.mCurrentExpandedYPosition += gap; } viewState.yTranslation = algorithmState.mCurrentYPosition; @@ -536,16 +545,29 @@ public class StackScrollAlgorithm { SectionProvider sectionProvider, int visibleIndex, View child, - View previousChild) { + View previousChild, + float fractionToShade, + boolean onKeyguard) { if (childNeedsGapHeight(sectionProvider, visibleIndex, child, previousChild)) { - return mGapHeight; + return getGapForLocation(fractionToShade, onKeyguard); } else { return 0; } } + @VisibleForTesting + float getGapForLocation(float fractionToShade, boolean onKeyguard) { + if (fractionToShade > 0f) { + return MathUtils.lerp(mGapHeightOnLockscreen, mGapHeight, fractionToShade); + } + if (onKeyguard) { + return mGapHeightOnLockscreen; + } + return mGapHeight; + } + /** * Does a given child need a gap, i.e spacing before a view? * diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java index 111cbbe81755..3ccef9d6eb14 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java @@ -23,12 +23,14 @@ import android.util.Log; import android.view.IWindowManager; import android.view.MotionEvent; +import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.statusbar.AutoHideUiElement; import javax.inject.Inject; /** A controller to control all auto-hide things. Also see {@link AutoHideUiElement}. */ +@SysUISingleton public class AutoHideController { private static final String TAG = "AutoHideController"; private static final long AUTO_HIDE_TIMEOUT_MS = 2250; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java index ccb37aeb18a9..61780cd53bb2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java @@ -40,6 +40,7 @@ import com.android.systemui.statusbar.policy.DataSaverController.Listener; import com.android.systemui.statusbar.policy.DeviceControlsController; import com.android.systemui.statusbar.policy.HotspotController; import com.android.systemui.statusbar.policy.HotspotController.Callback; +import com.android.systemui.statusbar.policy.SafetyController; import com.android.systemui.statusbar.policy.WalletController; import com.android.systemui.util.UserAwareController; import com.android.systemui.util.settings.SecureSettings; @@ -83,6 +84,7 @@ public class AutoTileManager implements UserAwareController { private final DeviceControlsController mDeviceControlsController; private final WalletController mWalletController; private final ReduceBrightColorsController mReduceBrightColorsController; + private final SafetyController mSafetyController; private final boolean mIsReduceBrightColorsAvailable; private final ArrayList<AutoAddSetting> mAutoAddSettingList = new ArrayList<>(); @@ -98,6 +100,7 @@ public class AutoTileManager implements UserAwareController { ReduceBrightColorsController reduceBrightColorsController, DeviceControlsController deviceControlsController, WalletController walletController, + SafetyController safetyController, @Named(RBC_AVAILABLE) boolean isReduceBrightColorsAvailable) { mContext = context; mHost = host; @@ -114,6 +117,7 @@ public class AutoTileManager implements UserAwareController { mIsReduceBrightColorsAvailable = isReduceBrightColorsAvailable; mDeviceControlsController = deviceControlsController; mWalletController = walletController; + mSafetyController = safetyController; String safetySpecRes; try { safetySpecRes = context.getResources().getString(R.string.safety_quick_settings_tile); @@ -163,8 +167,11 @@ public class AutoTileManager implements UserAwareController { if (!mAutoTracker.isAdded(WALLET)) { initWalletController(); } - if (mSafetySpec != null && !mAutoTracker.isAdded(mSafetySpec)) { - initSafetyTile(); + if (mSafetySpec != null) { + if (!mAutoTracker.isAdded(mSafetySpec)) { + initSafetyTile(); + } + mSafetyController.addCallback(mSafetyCallback); } int settingsN = mAutoAddSettingList.size(); @@ -187,6 +194,9 @@ public class AutoTileManager implements UserAwareController { } mCastController.removeCallback(mCastCallback); mDeviceControlsController.removeCallback(); + if (mSafetySpec != null) { + mSafetyController.removeCallback(mSafetyCallback); + } int settingsN = mAutoAddSettingList.size(); for (int i = 0; i < settingsN; i++) { mAutoAddSettingList.get(i).setListening(false); @@ -327,10 +337,9 @@ public class AutoTileManager implements UserAwareController { } private void initSafetyTile() { - if (mSafetySpec == null) { + if (mSafetySpec == null || mAutoTracker.isAdded(mSafetySpec)) { return; } - if (mAutoTracker.isAdded(mSafetySpec)) return; mHost.addTile(CustomTile.getComponentFromSpec(mSafetySpec), true); mAutoTracker.setTileAdded(mSafetySpec); } @@ -403,6 +412,23 @@ public class AutoTileManager implements UserAwareController { }; @VisibleForTesting + final SafetyController.Listener mSafetyCallback = new SafetyController.Listener() { + @Override + public void onSafetyCenterEnableChanged(boolean isSafetyCenterEnabled) { + if (mSafetySpec == null) { + return; + } + + if (isSafetyCenterEnabled && !mAutoTracker.isAdded(mSafetySpec)) { + initSafetyTile(); + } else if (!isSafetyCenterEnabled && mAutoTracker.isAdded(mSafetySpec)) { + mHost.removeTile(CustomTile.getComponentFromSpec(mSafetySpec)); + mHost.unmarkTileAsAutoAdded(mSafetySpec); + } + } + }; + + @VisibleForTesting protected SettingObserver getSecureSettingForKey(String key) { for (SettingObserver s : mAutoAddSettingList) { if (Objects.equals(key, s.getKey())) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java index c77b0d6721fb..5e81b5da2455 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java @@ -4404,8 +4404,7 @@ public class CentralSurfaces extends CoreStartable implements @Override public void onDozeAmountChanged(float linear, float eased) { if (mFeatureFlags.isEnabled(Flags.LOCKSCREEN_ANIMATIONS) - && !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal) - && !mBiometricUnlockController.isWakeAndUnlock()) { + && !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) { mLightRevealScrim.setRevealAmount(1f - linear); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt index 96fa8a5cfd71..34cd1ceeffc7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt @@ -20,11 +20,14 @@ import android.content.res.Configuration import android.graphics.Rect import android.os.LocaleList import android.view.View.LAYOUT_DIRECTION_RTL +import com.android.systemui.dagger.SysUISingleton import com.android.systemui.statusbar.policy.ConfigurationController import java.util.ArrayList +import javax.inject.Inject -class ConfigurationControllerImpl(context: Context) : ConfigurationController { +@SysUISingleton +class ConfigurationControllerImpl @Inject constructor(context: Context) : ConfigurationController { private val listeners: MutableList<ConfigurationController.ConfigurationListener> = ArrayList() private val lastConfig = Configuration() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java index 829cd3ad0aad..54d39fd673f6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java @@ -299,6 +299,17 @@ public class DozeParameters implements } /** + * Whether we're capable of controlling the screen off animation if we want to. This isn't + * possible if AOD isn't even enabled or if the flag is disabled, or if the display needs + * blanking. + */ + public boolean canControlUnlockedScreenOff() { + return getAlwaysOn() + && mFeatureFlags.isEnabled(Flags.LOCKSCREEN_ANIMATIONS) + && !getDisplayNeedsBlanking(); + } + + /** * Whether we want to control the screen off animation when the device is unlocked. If we do, * we'll animate in AOD before turning off the screen, rather than simply fading to black and * then abruptly showing AOD. @@ -308,8 +319,7 @@ public class DozeParameters implements * disabled for a11y. */ public boolean shouldControlUnlockedScreenOff() { - return canControlUnlockedScreenOff() - && mUnlockedScreenOffAnimationController.shouldPlayUnlockedScreenOffAnimation(); + return mUnlockedScreenOffAnimationController.shouldPlayUnlockedScreenOffAnimation(); } public boolean shouldDelayKeyguardShow() { @@ -341,16 +351,6 @@ public class DozeParameters implements return getAlwaysOn() && mKeyguardShowing; } - /** - * Whether we're capable of controlling the screen off animation if we want to. This isn't - * possible if AOD isn't even enabled or if the flag is disabled. - */ - public boolean canControlUnlockedScreenOff() { - return getAlwaysOn() - && mFeatureFlags.isEnabled(Flags.LOCKSCREEN_ANIMATIONS) - && !getDisplayNeedsBlanking(); - } - private boolean getBoolean(String propName, int resId) { return SystemProperties.getBoolean(propName, mResources.getBoolean(resId)); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java index 7d96240d0b36..69beaf56519f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -23,6 +23,7 @@ import android.content.Context; import android.content.res.ColorStateList; import android.hardware.biometrics.BiometricSourceType; import android.os.Handler; +import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.util.Log; @@ -164,58 +165,66 @@ public class KeyguardBouncer { // In split system user mode, we never unlock system user. return; } - ensureView(); - mIsScrimmed = isScrimmed; - // On the keyguard, we want to show the bouncer when the user drags up, but it's - // not correct to end the falsing session. We still need to verify if those touches - // are valid. - // Later, at the end of the animation, when the bouncer is at the top of the screen, - // onFullyShown() will be called and FalsingManager will stop recording touches. - if (isScrimmed) { - setExpansion(EXPANSION_VISIBLE); - } + try { + Trace.beginSection("KeyguardBouncer#show"); - if (resetSecuritySelection) { - // showPrimarySecurityScreen() updates the current security method. This is needed in - // case we are already showing and the current security method changed. - showPrimarySecurityScreen(); - } + ensureView(); + mIsScrimmed = isScrimmed; - if (mContainer.getVisibility() == View.VISIBLE || mShowingSoon) { - return; - } + // On the keyguard, we want to show the bouncer when the user drags up, but it's + // not correct to end the falsing session. We still need to verify if those touches + // are valid. + // Later, at the end of the animation, when the bouncer is at the top of the screen, + // onFullyShown() will be called and FalsingManager will stop recording touches. + if (isScrimmed) { + setExpansion(EXPANSION_VISIBLE); + } + + if (resetSecuritySelection) { + // showPrimarySecurityScreen() updates the current security method. This is needed + // in case we are already showing and the current security method changed. + showPrimarySecurityScreen(); + } + + if (mContainer.getVisibility() == View.VISIBLE || mShowingSoon) { + return; + } - final int activeUserId = KeyguardUpdateMonitor.getCurrentUser(); - final boolean isSystemUser = + final int activeUserId = KeyguardUpdateMonitor.getCurrentUser(); + final boolean isSystemUser = UserManager.isSplitSystemUser() && activeUserId == UserHandle.USER_SYSTEM; - final boolean allowDismissKeyguard = !isSystemUser && activeUserId == keyguardUserId; + final boolean allowDismissKeyguard = !isSystemUser && activeUserId == keyguardUserId; - // If allowed, try to dismiss the Keyguard. If no security auth (password/pin/pattern) is - // set, this will dismiss the whole Keyguard. Otherwise, show the bouncer. - if (allowDismissKeyguard && mKeyguardViewController.dismiss(activeUserId)) { - return; - } + // If allowed, try to dismiss the Keyguard. If no security auth (password/pin/pattern) + // is set, this will dismiss the whole Keyguard. Otherwise, show the bouncer. + if (allowDismissKeyguard && mKeyguardViewController.dismiss(activeUserId)) { + return; + } - // This condition may indicate an error on Android, so log it. - if (!allowDismissKeyguard) { - Log.w(TAG, "User can't dismiss keyguard: " + activeUserId + " != " + keyguardUserId); - } + // This condition may indicate an error on Android, so log it. + if (!allowDismissKeyguard) { + Log.w(TAG, "User can't dismiss keyguard: " + activeUserId + " != " + + keyguardUserId); + } - mShowingSoon = true; + mShowingSoon = true; - // Split up the work over multiple frames. - DejankUtils.removeCallbacks(mResetRunnable); - if (mKeyguardStateController.isFaceAuthEnabled() && !needsFullscreenBouncer() + // Split up the work over multiple frames. + DejankUtils.removeCallbacks(mResetRunnable); + if (mKeyguardStateController.isFaceAuthEnabled() && !needsFullscreenBouncer() && !mKeyguardUpdateMonitor.userNeedsStrongAuth() && !mKeyguardBypassController.getBypassEnabled()) { - mHandler.postDelayed(mShowRunnable, BOUNCER_FACE_DELAY); - } else { - DejankUtils.postAfterTraversal(mShowRunnable); - } + mHandler.postDelayed(mShowRunnable, BOUNCER_FACE_DELAY); + } else { + DejankUtils.postAfterTraversal(mShowRunnable); + } - mCallback.onBouncerVisiblityChanged(true /* shown */); - dispatchStartingToShow(); + mCallback.onBouncerVisiblityChanged(true /* shown */); + dispatchStartingToShow(); + } finally { + Trace.endSection(); + } } public boolean isScrimmed() { @@ -317,6 +326,7 @@ public class KeyguardBouncer { } public void hide(boolean destroyView) { + Trace.beginSection("KeyguardBouncer#hide"); if (isShowing()) { SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED, SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__HIDDEN); @@ -338,6 +348,7 @@ public class KeyguardBouncer { // be slow because of AM lock contention during unlocking. We can delay it a bit. mHandler.postDelayed(mRemoveViewRunnable, 50); } + Trace.endSection(); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt index 7db677ab6305..3e32b64ebe3a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt @@ -71,7 +71,13 @@ class KeyguardLiftController @Inject constructor( isListening = false updateListeningState() keyguardUpdateMonitor.requestFaceAuth(true) - keyguardUpdateMonitor.requestActiveUnlock() + if (keyguardUpdateMonitor.mRequestActiveUnlockOnWakeup) { + keyguardUpdateMonitor.requestActiveUnlock("wake-unlock," + + " extra=KeyguardLiftController") + } else if (keyguardUpdateMonitor.mInitiateActiveUnlockOnWakeup) { + keyguardUpdateMonitor.initiateActiveUnlock("wake-initiate," + + " extra=KeyguardLiftController") + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java index b6ad9f704bcd..16fddb420fc4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java @@ -93,7 +93,8 @@ public class LightBarTransitionsController implements Dumpable, Callbacks, mDisplayId = mContext.getDisplayId(); } - public void destroy(Context context) { + /** Call to cleanup the LightBarTransitionsController when done with it. */ + public void destroy() { mCommandQueue.removeCallback(this); mStatusBarStateController.removeCallback(this); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index 8deaa3444bb0..e46765b35692 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -317,8 +317,6 @@ public class NotificationPanelViewController extends PanelViewController { private boolean mShouldUseSplitNotificationShade; // The bottom padding reserved for elements of the keyguard measuring notifications private float mKeyguardNotificationBottomPadding; - // Space available for notifications. - private float mKeyguardNotificationAvailableSpace; // Current max allowed keyguard notifications determined by measuring the panel private int mMaxAllowedKeyguardNotifications; @@ -338,6 +336,7 @@ public class NotificationPanelViewController extends PanelViewController { private boolean mAnimateNextPositionUpdate; private float mQuickQsHeaderHeight; private ScreenOffAnimationController mScreenOffAnimationController; + private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; private int mTrackingPointer; private VelocityTracker mQsVelocityTracker; @@ -745,7 +744,8 @@ public class NotificationPanelViewController extends PanelViewController { KeyguardUnlockAnimationController keyguardUnlockAnimationController, NotificationListContainer notificationListContainer, PanelEventsEmitter panelEventsEmitter, - NotificationStackSizeCalculator notificationStackSizeCalculator) { + NotificationStackSizeCalculator notificationStackSizeCalculator, + UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) { super(view, falsingManager, dozeLog, @@ -846,6 +846,7 @@ public class NotificationPanelViewController extends PanelViewController { mAuthController = authController; mLockIconViewController = lockIconViewController; mScreenOffAnimationController = screenOffAnimationController; + mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; mRemoteInputManager = remoteInputManager; int currentMode = navigationModeController.addListener( @@ -901,7 +902,7 @@ public class NotificationPanelViewController extends PanelViewController { onTrackingStopped(false); instantCollapse(); } else { - fling(0f, false, 0.7f, false); + fling(0f, false, 1f, false); } } } @@ -1242,8 +1243,6 @@ public class NotificationPanelViewController extends PanelViewController { mMaxAllowedKeyguardNotifications); mNotificationStackScrollLayoutController.setKeyguardBottomPaddingForDebug( mKeyguardNotificationBottomPadding); - mNotificationStackScrollLayoutController.mKeyguardNotificationAvailableSpaceForDebug( - mKeyguardNotificationAvailableSpace); } else { // no max when not on the keyguard mNotificationStackScrollLayoutController.setMaxDisplayedNotifications(-1); @@ -1251,6 +1250,10 @@ public class NotificationPanelViewController extends PanelViewController { } } + private boolean shouldAvoidChangingNotificationsCount() { + return mHintAnimationRunning || mUnlockedScreenOffAnimationController.isAnimationPlaying(); + } + public void setKeyguardIndicationController(KeyguardIndicationController indicationController) { mKeyguardIndicationController = indicationController; mKeyguardIndicationController.setIndicationArea(mKeyguardBottomArea); @@ -1461,13 +1464,11 @@ public class NotificationPanelViewController extends PanelViewController { * @return the maximum keyguard notifications that can fit on the screen */ private int computeMaxKeyguardNotifications() { - int notificationPadding = Math.max( - 1, mResources.getDimensionPixelSize(R.dimen.notification_divider_height)); float topPadding = mNotificationStackScrollLayoutController.getTopPadding(); - float shelfHeight = + float shelfIntrinsicHeight = mNotificationShelfController.getVisibility() == View.GONE ? 0 - : mNotificationShelfController.getIntrinsicHeight() + notificationPadding; + : mNotificationShelfController.getIntrinsicHeight(); // Padding to add to the bottom of the stack to keep a minimum distance from the top of // the lock icon. @@ -1486,13 +1487,11 @@ public class NotificationPanelViewController extends PanelViewController { float availableSpace = mNotificationStackScrollLayoutController.getHeight() - topPadding - - shelfHeight - bottomPadding; - mKeyguardNotificationAvailableSpace = availableSpace; return mNotificationStackSizeCalculator.computeMaxKeyguardNotifications( mNotificationStackScrollLayoutController.getView(), availableSpace, - shelfHeight); + shelfIntrinsicHeight); } private void updateClock() { @@ -2156,8 +2155,6 @@ public class NotificationPanelViewController extends PanelViewController { mNotificationsQSContainerController.setQsExpanded(expanded); mPulseExpansionHandler.setQsExpanded(expanded); mKeyguardBypassController.setQSExpanded(expanded); - mStatusBarKeyguardViewManager.setQsExpanded(expanded); - mLockIconViewController.setQsExpanded(expanded); mPrivacyDotViewController.setQsExpanded(expanded); } } @@ -2270,6 +2267,7 @@ public class NotificationPanelViewController extends PanelViewController { } mDepthController.setQsPanelExpansion(qsExpansionFraction); + mStatusBarKeyguardViewManager.setQsExpansion(qsExpansionFraction); // updateQsExpansion will get called whenever mTransitionToFullShadeProgress or // mLockscreenShadeTransitionController.getDragProgress change. @@ -3166,7 +3164,10 @@ public class NotificationPanelViewController extends PanelViewController { mFalsingCollector.onTrackingStarted(!mKeyguardStateController.canDismissLockScreen()); super.onTrackingStarted(); mScrimController.onTrackingStarted(); - if (mShouldUseSplitNotificationShade) { + // normally we want to set mQsExpandImmediate for every split shade case (at least when + // expanding), but keyguard tracking logic is different - this callback is called when + // unlocking with swipe up but not when swiping down to reveal shade + if (mShouldUseSplitNotificationShade && !mKeyguardShowing) { mQsExpandImmediate = true; } if (mQsFullyExpanded) { @@ -3208,7 +3209,7 @@ public class NotificationPanelViewController extends PanelViewController { @Override protected void startUnlockHintAnimation() { - if (mPowerManager.isPowerSaveMode()) { + if (mPowerManager.isPowerSaveMode() || mAmbientState.getDozeAmount() > 0f) { onUnlockHintStarted(); onUnlockHintFinished(); return; @@ -3334,6 +3335,12 @@ public class NotificationPanelViewController extends PanelViewController { .log(LockscreenUiEvent.LOCKSCREEN_LOCK_SHOW_HINT); startUnlockHintAnimation(); } + if (mUpdateMonitor.isFaceEnrolled() + && mUpdateMonitor.mRequestActiveUnlockOnUnlockIntent + && mKeyguardBypassController.canBypass()) { + mUpdateMonitor.requestActiveUnlock("unlock-intent," + + " extra=lockScreenEmptySpaceTap", true); + } } return true; case StatusBarState.SHADE_LOCKED: @@ -4733,7 +4740,7 @@ public class NotificationPanelViewController extends PanelViewController { int oldTop, int oldRight, int oldBottom) { DejankUtils.startDetectingBlockingIpcs("NVP#onLayout"); super.onLayoutChange(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom); - updateMaxDisplayedNotifications(true); + updateMaxDisplayedNotifications(!shouldAvoidChangingNotificationsCount()); setIsFullWidth(mNotificationStackScrollLayoutController.getWidth() == mView.getWidth()); // Update Clock Pivot diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java index 56c74bf98e6b..24660b261c51 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java @@ -288,7 +288,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW final boolean keyguardOrAod = state.mKeyguardShowing || (state.mDozing && mDozeParameters.getAlwaysOn()); if ((keyguardOrAod && !state.mBackdropShowing && !state.mLightRevealScrimOpaque) - || mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe()) { + || mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehind()) { // Show the wallpaper if we're on keyguard/AOD and the wallpaper is not occluded by a // solid backdrop. Also, show it if we are currently animating between the // keyguard and the surface behind the keyguard - we want to use the wallpaper as a diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java index 518a9181ec98..4ba8441fc9a6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java @@ -48,7 +48,6 @@ import android.view.animation.Interpolator; import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.LatencyTracker; -import com.android.keyguard.BouncerPanelExpansionCalculator; import com.android.systemui.DejankUtils; import com.android.systemui.R; import com.android.systemui.animation.Interpolators; @@ -796,9 +795,7 @@ public abstract class PanelViewController { } mExpandedFraction = Math.min(1f, maxPanelHeight == 0 ? 0 : mExpandedHeight / maxPanelHeight); - mAmbientState.setExpansionFraction(mStatusBarKeyguardViewManager.bouncerIsInTransit() - ? BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(mExpandedFraction) - : mExpandedFraction); + mAmbientState.setExpansionFraction(mExpandedFraction); onHeightUpdated(mExpandedHeight); updatePanelExpansionAndVisibility(); }); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java index 26ffdf25318d..290df3e3e1af 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -292,9 +292,7 @@ public class PhoneStatusBarPolicy mIconController.setIconVisibility(mSlotHotspot, mHotspot.isHotspotEnabled()); // managed profile - mIconController.setIcon(mSlotManagedProfile, R.drawable.stat_sys_managed_profile_status, - getManagedProfileAccessibilityString()); - mIconController.setIconVisibility(mSlotManagedProfile, mManagedProfileIconVisible); + updateManagedProfile(); // data saver mIconController.setIcon(mSlotDataSaver, R.drawable.stat_sys_data_saver, @@ -521,7 +519,7 @@ public class PhoneStatusBarPolicy } private void updateManagedProfile() { - // getLastResumedActivityUserId needds to acquire the AM lock, which may be contended in + // getLastResumedActivityUserId needs to acquire the AM lock, which may be contended in // some cases. Since it doesn't really matter here whether it's updated in this frame // or in the next one, we call this method from our UI offload thread. mUiBgExecutor.execute(() -> { @@ -529,6 +527,7 @@ public class PhoneStatusBarPolicy try { userId = ActivityTaskManager.getService().getLastResumedActivityUserId(); boolean isManagedProfile = mUserManager.isManagedProfile(userId); + String accessibilityString = getManagedProfileAccessibilityString(); mHandler.post(() -> { final boolean showIcon; if (isManagedProfile && (!mKeyguardStateController.isShowing() @@ -536,7 +535,7 @@ public class PhoneStatusBarPolicy showIcon = true; mIconController.setIcon(mSlotManagedProfile, R.drawable.stat_sys_managed_profile_status, - getManagedProfileAccessibilityString()); + accessibilityString); } else { showIcon = false; } 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 fd6503a53208..8c1ed19a8dcc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -790,7 +790,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump if (mBouncerHiddenFraction != KeyguardBouncer.EXPANSION_HIDDEN) { final float interpolatedFraction = - BouncerPanelExpansionCalculator.getBackScrimScaledExpansion( + BouncerPanelExpansionCalculator.aboutToShowBouncerProgress( mBouncerHiddenFraction); mBehindAlpha = MathUtils.lerp(mDefaultScrimAlpha, mBehindAlpha, interpolatedFraction); @@ -1074,9 +1074,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump } private float getInterpolatedFraction() { - if (mStatusBarKeyguardViewManager.bouncerIsInTransit()) { + if (mStatusBarKeyguardViewManager.isBouncerInTransit()) { return BouncerPanelExpansionCalculator - .getBackScrimScaledExpansion(mPanelExpansionFraction); + .aboutToShowBouncerProgress(mPanelExpansionFraction); } return ShadeInterpolation.getNotificationScrimAlpha(mPanelExpansionFraction); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index ce1289e0885c..dd166dd3610e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -164,7 +164,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb @Override public void onVisibilityChanged(boolean isVisible) { if (!isVisible) { - cancelPostAuthActions(); mCentralSurfaces.setBouncerHiddenFraction(KeyguardBouncer.EXPANSION_HIDDEN); } if (mAlternateAuthInterceptor != null) { @@ -218,7 +217,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb private boolean mLastPulsing; private int mLastBiometricMode; private boolean mLastScreenOffAnimationPlaying; - private boolean mQsExpanded; + private float mQsExpansion; private OnDismissAction mAfterKeyguardGoneAction; private Runnable mKeyguardGoneCancelAction; @@ -502,42 +501,52 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb public void dismissWithAction(OnDismissAction r, Runnable cancelAction, boolean afterKeyguardGone, String message) { if (mShowing) { - cancelPendingWakeupAction(); - // If we're dozing, this needs to be delayed until after we wake up - unless we're - // wake-and-unlocking, because there dozing will last until the end of the transition. - if (mDozing && !isWakeAndUnlocking()) { - mPendingWakeupAction = new DismissWithActionRequest( - r, cancelAction, afterKeyguardGone, message); - return; - } + try { + Trace.beginSection("StatusBarKeyguardViewManager#dismissWithAction"); + cancelPendingWakeupAction(); + // If we're dozing, this needs to be delayed until after we wake up - unless we're + // wake-and-unlocking, because there dozing will last until the end of the + // transition. + if (mDozing && !isWakeAndUnlocking()) { + mPendingWakeupAction = new DismissWithActionRequest( + r, cancelAction, afterKeyguardGone, message); + return; + } + + mAfterKeyguardGoneAction = r; + mKeyguardGoneCancelAction = cancelAction; + mDismissActionWillAnimateOnKeyguard = r != null && r.willRunAnimationOnKeyguard(); + + // If there is an an alternate auth interceptor (like the UDFPS), show that one + // instead of the bouncer. + if (shouldShowAltAuth()) { + if (!afterKeyguardGone) { + mBouncer.setDismissAction(mAfterKeyguardGoneAction, + mKeyguardGoneCancelAction); + mAfterKeyguardGoneAction = null; + mKeyguardGoneCancelAction = null; + } - mAfterKeyguardGoneAction = r; - mKeyguardGoneCancelAction = cancelAction; - mDismissActionWillAnimateOnKeyguard = r != null && r.willRunAnimationOnKeyguard(); + updateAlternateAuthShowing( + mAlternateAuthInterceptor.showAlternateAuthBouncer()); + return; + } - // If there is an an alternate auth interceptor (like the UDFPS), show that one instead - // of the bouncer. - if (shouldShowAltAuth()) { - if (!afterKeyguardGone) { - mBouncer.setDismissAction(mAfterKeyguardGoneAction, mKeyguardGoneCancelAction); + if (afterKeyguardGone) { + // we'll handle the dismiss action after keyguard is gone, so just show the + // bouncer + mBouncer.show(false /* resetSecuritySelection */); + } else { + // after authentication success, run dismiss action with the option to defer + // hiding the keyguard based on the return value of the OnDismissAction + mBouncer.showWithDismissAction(mAfterKeyguardGoneAction, + mKeyguardGoneCancelAction); + // bouncer will handle the dismiss action, so we no longer need to track it here mAfterKeyguardGoneAction = null; mKeyguardGoneCancelAction = null; } - - updateAlternateAuthShowing(mAlternateAuthInterceptor.showAlternateAuthBouncer()); - return; - } - - if (afterKeyguardGone) { - // we'll handle the dismiss action after keyguard is gone, so just show the bouncer - mBouncer.show(false /* resetSecuritySelection */); - } else { - // after authentication success, run dismiss action with the option to defer - // hiding the keyguard based on the return value of the OnDismissAction - mBouncer.showWithDismissAction(mAfterKeyguardGoneAction, mKeyguardGoneCancelAction); - // bouncer will handle the dismiss action, so we no longer need to track it here - mAfterKeyguardGoneAction = null; - mKeyguardGoneCancelAction = null; + } finally { + Trace.endSection(); } } updateStates(); @@ -580,9 +589,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } } - /** - * Stop showing any alternate auth methods - */ + @Override public void resetAlternateAuth(boolean forceUpdateScrim) { final boolean updateScrim = (mAlternateAuthInterceptor != null && mAlternateAuthInterceptor.hideAlternateAuthBouncer()) @@ -591,10 +598,12 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } private void updateAlternateAuthShowing(boolean updateScrim) { + final boolean isShowingAltAuth = isShowingAlternateAuth(); if (mKeyguardMessageAreaController != null) { - mKeyguardMessageAreaController.setAltBouncerShowing(isShowingAlternateAuth()); + mKeyguardMessageAreaController.setAltBouncerShowing(isShowingAltAuth); } - mBypassController.setAltBouncerShowing(isShowingAlternateAuth()); + mBypassController.setAltBouncerShowing(isShowingAltAuth); + mKeyguardUpdateManager.setUdfpsBouncerShowing(isShowingAltAuth); if (updateScrim) { mCentralSurfaces.updateScrimController(); @@ -1270,6 +1279,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb pw.println(" mAfterKeyguardGoneAction: " + mAfterKeyguardGoneAction); pw.println(" mAfterKeyguardGoneRunnables: " + mAfterKeyguardGoneRunnables); pw.println(" mPendingWakeupAction: " + mPendingWakeupAction); + pw.println(" isBouncerShowing(): " + isBouncerShowing()); + pw.println(" bouncerIsOrWillBeShowing(): " + bouncerIsOrWillBeShowing()); if (mBouncer != null) { mBouncer.dump(pw); @@ -1296,16 +1307,17 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb /** * Whether qs is currently expanded. */ - public boolean isQsExpanded() { - return mQsExpanded; + public float getQsExpansion() { + return mQsExpansion; } + /** - * Set whether qs is currently expanded + * Update qs expansion. */ - public void setQsExpanded(boolean expanded) { - mQsExpanded = expanded; + public void setQsExpansion(float qsExpansion) { + mQsExpansion = qsExpansion; if (mAlternateAuthInterceptor != null) { - mAlternateAuthInterceptor.setQsExpanded(expanded); + mAlternateAuthInterceptor.setQsExpansion(qsExpansion); } } @@ -1378,7 +1390,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb /** * Returns if bouncer expansion is between 0 and 1 non-inclusive. */ - public boolean bouncerIsInTransit() { + public boolean isBouncerInTransit() { if (mBouncer == null) return false; return mBouncer.inTransit(); @@ -1417,9 +1429,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb boolean isAnimating(); /** - * Set whether qs is currently expanded. + * How much QS is fully expanded where 0f is not showing and 1f is fully expanded. */ - void setQsExpanded(boolean expanded); + void setQsExpansion(float qsExpansion); /** * Forward potential touches to authentication interceptor diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialogManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialogManager.java index 36e705a31a10..e7d9221ac861 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialogManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialogManager.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.phone; import androidx.annotation.NonNull; +import com.android.keyguard.KeyguardViewController; import com.android.systemui.Dumpable; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dump.DumpManager; @@ -37,7 +38,7 @@ import javax.inject.Inject; */ @SysUISingleton public class SystemUIDialogManager implements Dumpable { - private final StatusBarKeyguardViewManager mKeyguardViewManager; + private final KeyguardViewController mKeyguardViewController; private final Set<SystemUIDialog> mDialogsShowing = new HashSet<>(); private final Set<Listener> mListeners = new HashSet<>(); @@ -45,9 +46,9 @@ public class SystemUIDialogManager implements Dumpable { @Inject public SystemUIDialogManager( DumpManager dumpManager, - StatusBarKeyguardViewManager statusBarKeyguardViewManager) { + KeyguardViewController keyguardViewController) { dumpManager.registerDumpable(this); - mKeyguardViewManager = statusBarKeyguardViewManager; + mKeyguardViewController = keyguardViewController; } /** @@ -86,7 +87,7 @@ public class SystemUIDialogManager implements Dumpable { private void updateDialogListeners() { if (shouldHideAffordance()) { - mKeyguardViewManager.resetAlternateAuth(true); + mKeyguardViewController.resetAlternateAuth(true); } for (Listener listener : mListeners) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt index c11d450e47b2..935f87dc8221 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt @@ -17,6 +17,7 @@ import com.android.systemui.animation.Interpolators import com.android.systemui.dagger.SysUISingleton import com.android.systemui.keyguard.KeyguardViewMediator import com.android.systemui.keyguard.WakefulnessLifecycle +import com.android.systemui.statusbar.CircleReveal import com.android.systemui.statusbar.LightRevealScrim import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.StatusBarStateControllerImpl @@ -59,8 +60,14 @@ class UnlockedScreenOffAnimationController @Inject constructor( private val powerManager: PowerManager, private val handler: Handler = Handler() ) : WakefulnessLifecycle.Observer, ScreenOffAnimation { - private lateinit var mCentralSurfaces: CentralSurfaces + /** + * Whether or not [initialize] has been called to provide us with the StatusBar, + * NotificationPanelViewController, and LightRevealSrim so that we can run the unlocked screen + * off animation. + */ + private var initialized = false + private lateinit var lightRevealScrim: LightRevealScrim private var animatorDurationScale = 1f @@ -79,7 +86,9 @@ class UnlockedScreenOffAnimationController @Inject constructor( duration = LIGHT_REVEAL_ANIMATION_DURATION interpolator = Interpolators.LINEAR addUpdateListener { - lightRevealScrim.revealAmount = it.animatedValue as Float + if (lightRevealScrim.revealEffect !is CircleReveal) { + lightRevealScrim.revealAmount = it.animatedValue as Float + } if (lightRevealScrim.isScrimAlmostOccludes && interactionJankMonitor.isInstrumenting(CUJ_SCREEN_OFF)) { // ends the instrument when the scrim almost occludes the screen. @@ -89,9 +98,9 @@ class UnlockedScreenOffAnimationController @Inject constructor( } addListener(object : AnimatorListenerAdapter() { override fun onAnimationCancel(animation: Animator?) { - lightRevealScrim.revealAmount = 1f - lightRevealAnimationPlaying = false - interactionJankMonitor.cancel(CUJ_SCREEN_OFF) + if (lightRevealScrim.revealEffect !is CircleReveal) { + lightRevealScrim.revealAmount = 1f + } } override fun onAnimationEnd(animation: Animator?) { @@ -116,6 +125,7 @@ class UnlockedScreenOffAnimationController @Inject constructor( centralSurfaces: CentralSurfaces, lightRevealScrim: LightRevealScrim ) { + this.initialized = true this.lightRevealScrim = lightRevealScrim this.mCentralSurfaces = centralSurfaces @@ -262,6 +272,18 @@ class UnlockedScreenOffAnimationController @Inject constructor( * on the current state of the device. */ fun shouldPlayUnlockedScreenOffAnimation(): Boolean { + // If we haven't been initialized yet, we don't have a StatusBar/LightRevealScrim yet, so we + // can't perform the animation. + if (!initialized) { + return false + } + + // If the device isn't in a state where we can control unlocked screen off (no AOD enabled, + // power save, etc.) then we shouldn't try to do so. + if (!dozeParameters.get().canControlUnlockedScreenOff()) { + return false + } + // If we explicitly already decided not to play the screen off animation, then never change // our mind. if (decidedToAnimateGoingToSleep == false) { @@ -304,7 +326,7 @@ class UnlockedScreenOffAnimationController @Inject constructor( } override fun shouldDelayDisplayDozeTransition(): Boolean = - dozeParameters.get().shouldControlUnlockedScreenOff() + shouldPlayUnlockedScreenOffAnimation() /** * Whether we're doing the light reveal animation or we're done with that and animating in the diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java index c404cf69f1a8..1b93c16dd45c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java @@ -137,4 +137,8 @@ public class UserAvatarView extends View { mDrawable.setIconDrawable(d); mDrawable.setBadgeIfManagedUser(getContext(), userId); } + + public boolean isEmpty() { + return mDrawable.isEmpty(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java index e8bf89a6a90a..2a9048a6eb73 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java @@ -29,6 +29,7 @@ import android.view.ViewGroup; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.UiEventLogger; import com.android.keyguard.KeyguardConstants; import com.android.keyguard.KeyguardVisibilityHelper; @@ -36,7 +37,6 @@ import com.android.keyguard.dagger.KeyguardUserSwitcherScope; import com.android.settingslib.drawable.CircleFramedDrawable; import com.android.systemui.R; import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.user.UserSwitchDialogController; @@ -68,7 +68,6 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> private final Context mContext; private Resources mResources; private final UserSwitcherController mUserSwitcherController; - private final ScreenLifecycle mScreenLifecycle; private UserSwitcherController.BaseUserAdapter mAdapter; private final KeyguardStateController mKeyguardStateController; private final FalsingManager mFalsingManager; @@ -77,8 +76,10 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> private final KeyguardVisibilityHelper mKeyguardVisibilityHelper; private final UserSwitchDialogController mUserSwitchDialogController; private final UiEventLogger mUiEventLogger; - private UserAvatarView mUserAvatarView; + @VisibleForTesting + UserAvatarView mUserAvatarView; UserSwitcherController.UserRecord mCurrentUser; + private boolean mIsKeyguardShowing; // State info for the user switch and keyguard private int mBarState; @@ -87,8 +88,6 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> new StatusBarStateController.StateListener() { @Override public void onStateChanged(int newState) { - if (DEBUG) Log.d(TAG, String.format("onStateChanged: newState=%d", newState)); - boolean goingToFullShade = mStatusBarStateController.goingToFullShade(); boolean keyguardFadingAway = mKeyguardStateController.isKeyguardFadingAway(); int oldState = mBarState; @@ -102,12 +101,34 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> } }; - private ConfigurationController.ConfigurationListener - mConfigurationListener = new ConfigurationController.ConfigurationListener() { + private ConfigurationController.ConfigurationListener mConfigurationListener = + new ConfigurationController.ConfigurationListener() { @Override public void onUiModeChanged() { - updateView(true); + // Force update when dark theme toggled. Otherwise, icon will not update + // until it is clicked + if (mIsKeyguardShowing) { + updateView(); + } + } + }; + + private final KeyguardStateController.Callback mKeyguardStateCallback = + new KeyguardStateController.Callback() { + @Override + public void onUnlockedChanged() { + updateKeyguardShowing(false /* forceViewUpdate */); + } + + @Override + public void onKeyguardShowingChanged() { + updateKeyguardShowing(false /* forceViewUpdate */); + } + + @Override + public void onKeyguardFadingAwayChanged() { + updateKeyguardShowing(false /* forceViewUpdate */); } }; @@ -116,7 +137,6 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> FrameLayout view, Context context, @Main Resources resources, - ScreenLifecycle screenLifecycle, UserSwitcherController userSwitcherController, KeyguardStateController keyguardStateController, FalsingManager falsingManager, @@ -130,7 +150,6 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> if (DEBUG) Log.d(TAG, "New KeyguardQsUserSwitchController"); mContext = context; mResources = resources; - mScreenLifecycle = screenLifecycle; mUserSwitcherController = userSwitcherController; mKeyguardStateController = keyguardStateController; mFalsingManager = falsingManager; @@ -188,7 +207,10 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> mDataSetObserver.onChanged(); mStatusBarStateController.addCallback(mStatusBarStateListener); mConfigurationController.addCallback(mConfigurationListener); - updateView(true /* forceUpdate */); + mKeyguardStateController.addCallback(mKeyguardStateCallback); + // Force update when view attached in case configuration changed while the view was detached + updateCurrentUser(); + updateKeyguardShowing(true /* forceViewUpdate */); } @Override @@ -198,15 +220,48 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> mAdapter.unregisterDataSetObserver(mDataSetObserver); mStatusBarStateController.removeCallback(mStatusBarStateListener); mConfigurationController.removeCallback(mConfigurationListener); + mKeyguardStateController.removeCallback(mKeyguardStateCallback); } public final DataSetObserver mDataSetObserver = new DataSetObserver() { @Override public void onChanged() { - updateView(false /* forceUpdate */); + boolean userChanged = updateCurrentUser(); + if (userChanged || (mIsKeyguardShowing && mUserAvatarView.isEmpty())) { + updateView(); + } } }; + private void clearAvatar() { + if (DEBUG) Log.d(TAG, "clearAvatar"); + mUserAvatarView.setAvatar(null); + } + + /** + * @param forceViewUpdate whether view should be updated regardless of whether + * keyguard-showing state changed + */ + @VisibleForTesting + void updateKeyguardShowing(boolean forceViewUpdate) { + boolean wasKeyguardShowing = mIsKeyguardShowing; + mIsKeyguardShowing = mKeyguardStateController.isShowing() + || mKeyguardStateController.isKeyguardGoingAway(); + if (wasKeyguardShowing == mIsKeyguardShowing && !forceViewUpdate) { + return; + } + if (DEBUG) { + Log.d(TAG, "updateKeyguardShowing:" + + " mIsKeyguardShowing=" + mIsKeyguardShowing + + " forceViewUpdate=" + forceViewUpdate); + } + if (mIsKeyguardShowing) { + updateView(); + } else { + clearAvatar(); + } + } + /** * @return true if the current user has changed */ @@ -223,31 +278,22 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> return mCurrentUser == null && previousUser != null; } - /** - * @param forceUpdate whether to update view even if current user did not change - */ - private void updateView(boolean forceUpdate) { - if (!updateCurrentUser() && !forceUpdate) { - return; - } - - String contentDescription = null; - if (mCurrentUser != null && mCurrentUser.info != null && !TextUtils.isEmpty( - mCurrentUser.info.name)) { + private String getContentDescription() { + if (mCurrentUser != null && mCurrentUser.info != null + && !TextUtils.isEmpty(mCurrentUser.info.name)) { // If we know the current user's name, have TalkBack to announce "Signed in as [user // name]" when the icon is selected - contentDescription = mContext.getString(R.string.accessibility_quick_settings_user, - mCurrentUser.info.name); + return mContext.getString( + R.string.accessibility_quick_settings_user, mCurrentUser.info.name); } else { // As a fallback, have TalkBack announce "Switch user" - contentDescription = mContext.getString( - R.string.accessibility_multi_user_switch_switcher); - } - - if (!TextUtils.equals(mUserAvatarView.getContentDescription(), contentDescription)) { - mUserAvatarView.setContentDescription(contentDescription); + return mContext.getString(R.string.accessibility_multi_user_switch_switcher); } + } + private void updateView() { + if (DEBUG) Log.d(TAG, "updateView"); + mUserAvatarView.setContentDescription(getContentDescription()); int userId = mCurrentUser != null ? mCurrentUser.resolveId() : UserHandle.USER_NULL; mUserAvatarView.setDrawableWithBadge(getCurrentUserIcon().mutate(), userId); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SafetyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SafetyController.java new file mode 100644 index 000000000000..f3d183ceb45f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SafetyController.java @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.policy; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.os.Handler; +import android.safetycenter.SafetyCenterManager; + +import androidx.annotation.NonNull; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.dagger.qualifiers.Background; + +import java.util.ArrayList; +import java.util.Objects; + +import javax.inject.Inject; + +/** + * Controller which calls listeners when a PACKAGE_CHANGED broadcast is sent for the + * PermissionController. These broadcasts may be because the PermissionController enabled or + * disabled its TileService, and the tile should be added if the component was enabled, or removed + * if disabled. + */ +public class SafetyController implements + CallbackController<SafetyController.Listener> { + private boolean mSafetyCenterEnabled; + private final Handler mBgHandler; + private final ArrayList<Listener> mListeners = new ArrayList<>(); + private static final IntentFilter PKG_CHANGE_INTENT_FILTER; + private final Context mContext; + private final SafetyCenterManager mSafetyCenterManager; + private final PackageManager mPackageManager; + + static { + PKG_CHANGE_INTENT_FILTER = new IntentFilter(Intent.ACTION_PACKAGE_CHANGED); + PKG_CHANGE_INTENT_FILTER.addDataScheme("package"); + } + + @Inject + public SafetyController(Context context, PackageManager pm, SafetyCenterManager scm, + @Background Handler bgHandler) { + mContext = context; + mSafetyCenterManager = scm; + mPackageManager = pm; + mBgHandler = bgHandler; + mSafetyCenterEnabled = mSafetyCenterManager.isSafetyCenterEnabled(); + } + + public boolean isSafetyCenterEnabled() { + return mSafetyCenterEnabled; + } + + /** + * Adds a listener, registering the broadcast receiver if need be. Immediately calls the + * provided listener on the calling thread. + */ + @Override + public void addCallback(@NonNull Listener listener) { + synchronized (mListeners) { + mListeners.add(listener); + if (mListeners.size() == 1) { + mContext.registerReceiver(mPermControllerChangeReceiver, PKG_CHANGE_INTENT_FILTER); + mBgHandler.post(() -> { + mSafetyCenterEnabled = mSafetyCenterManager.isSafetyCenterEnabled(); + listener.onSafetyCenterEnableChanged(isSafetyCenterEnabled()); + }); + } else { + listener.onSafetyCenterEnableChanged(isSafetyCenterEnabled()); + } + } + } + + @Override + public void removeCallback(@NonNull Listener listener) { + synchronized (mListeners) { + mListeners.remove(listener); + if (mListeners.isEmpty()) { + mContext.unregisterReceiver(mPermControllerChangeReceiver); + } + } + } + + private void handleSafetyCenterEnableChange() { + synchronized (mListeners) { + for (int i = 0; i < mListeners.size(); i++) { + mListeners.get(i).onSafetyCenterEnableChanged(mSafetyCenterEnabled); + } + } + } + + /** + * Upon receiving a package changed broadcast for the PermissionController, checks if the + * safety center is enabled or disabled, and sends an update on the main thread if the state + * changed. + */ + @VisibleForTesting + final BroadcastReceiver mPermControllerChangeReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String packageName = intent.getData() != null ? intent.getData().getSchemeSpecificPart() + : null; + if (!Objects.equals(packageName, + mPackageManager.getPermissionControllerPackageName())) { + return; + } + + boolean wasSafetyCenterEnabled = mSafetyCenterEnabled; + mSafetyCenterEnabled = mSafetyCenterManager.isSafetyCenterEnabled(); + if (wasSafetyCenterEnabled == mSafetyCenterEnabled) { + return; + } + + mBgHandler.post(() -> handleSafetyCenterEnableChange()); + } + }; + + /** + * Listener for safety center enabled changes + */ + public interface Listener { + /** + * Callback to be notified when the safety center is enabled or disabled + * @param isSafetyCenterEnabled If the safety center is enabled + */ + void onSafetyCenterEnableChanged(boolean isSafetyCenterEnabled); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java index 846e07fa0bad..a3f01c21d137 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java @@ -64,8 +64,6 @@ import com.android.settingslib.users.UserCreatingDialog; import com.android.settingslib.utils.ThreadUtils; import com.android.systemui.Dumpable; import com.android.systemui.GuestResumeSessionReceiver; -import com.android.systemui.Prefs; -import com.android.systemui.Prefs.Key; import com.android.systemui.R; import com.android.systemui.SystemUISecondaryUserService; import com.android.systemui.animation.DialogLaunchAnimator; @@ -84,6 +82,7 @@ import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.telephony.TelephonyListenerManager; import com.android.systemui.user.CreateUserActivity; +import com.android.systemui.util.settings.GlobalSettings; import com.android.systemui.util.settings.SecureSettings; import java.io.PrintWriter; @@ -144,6 +143,7 @@ public class UserSwitcherController implements Dumpable { // When false, there won't be any visual affordance to add a new user from the keyguard even if // the user is unlocked private boolean mAddUsersFromLockScreen; + private boolean mUserSwitcherEnabled; @VisibleForTesting boolean mPauseRefreshUsers; private int mSecondaryUser = UserHandle.USER_NULL; @@ -160,6 +160,7 @@ public class UserSwitcherController implements Dumpable { private FalsingManager mFalsingManager; private View mView; private String mCreateSupervisedUserPackage; + private GlobalSettings mGlobalSettings; @Inject public UserSwitcherController(Context context, @@ -177,6 +178,7 @@ public class UserSwitcherController implements Dumpable { FalsingManager falsingManager, TelephonyListenerManager telephonyListenerManager, SecureSettings secureSettings, + GlobalSettings globalSettings, @Background Executor bgExecutor, @LongRunning Executor longRunningExecutor, @Main Executor uiExecutor, @@ -194,6 +196,7 @@ public class UserSwitcherController implements Dumpable { mFalsingManager = falsingManager; mInteractionJankMonitor = interactionJankMonitor; mLatencyTracker = latencyTracker; + mGlobalSettings = globalSettings; mGuestResumeSessionReceiver = new GuestResumeSessionReceiver( this, mUserTracker, mUiEventLogger, secureSettings); mBgExecutor = bgExecutor; @@ -237,8 +240,10 @@ public class UserSwitcherController implements Dumpable { @Override public void onChange(boolean selfChange) { mSimpleUserSwitcher = shouldUseSimpleUserSwitcher(); - mAddUsersFromLockScreen = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.ADD_USERS_WHEN_LOCKED, 0) != 0; + mAddUsersFromLockScreen = mGlobalSettings.getIntForUser( + Settings.Global.ADD_USERS_WHEN_LOCKED, 0, UserHandle.USER_SYSTEM) != 0; + mUserSwitcherEnabled = mGlobalSettings.getIntForUser( + Settings.Global.USER_SWITCHER_ENABLED, 0, UserHandle.USER_SYSTEM) != 0; refreshUsers(UserHandle.USER_NULL); }; }; @@ -246,6 +251,9 @@ public class UserSwitcherController implements Dumpable { Settings.Global.getUriFor(SIMPLE_USER_SWITCHER_GLOBAL_SETTING), true, mSettingsObserver); mContext.getContentResolver().registerContentObserver( + Settings.Global.getUriFor(Settings.Global.USER_SWITCHER_ENABLED), true, + mSettingsObserver); + mContext.getContentResolver().registerContentObserver( Settings.Global.getUriFor(Settings.Global.ADD_USERS_WHEN_LOCKED), true, mSettingsObserver); mContext.getContentResolver().registerContentObserver( @@ -314,6 +322,10 @@ public class UserSwitcherController implements Dumpable { for (UserInfo info : infos) { boolean isCurrent = currentId == info.id; boolean switchToEnabled = canSwitchUsers || isCurrent; + if (!mUserSwitcherEnabled && !info.isPrimary()) { + continue; + } + if (info.isEnabled()) { if (info.isGuest()) { // Tapping guest icon triggers remove and a user switch therefore @@ -340,9 +352,6 @@ public class UserSwitcherController implements Dumpable { } } } - if (records.size() > 1 || guestRecord != null) { - Prefs.putBoolean(mContext, Key.SEEN_MULTI_USER, true); - } if (guestRecord == null) { if (mGuestUserAutoCreated) { @@ -411,12 +420,14 @@ public class UserSwitcherController implements Dumpable { } boolean canCreateGuest(boolean hasExistingGuest) { - return (currentUserCanCreateUsers() || anyoneCanCreateUsers()) + return mUserSwitcherEnabled + && (currentUserCanCreateUsers() || anyoneCanCreateUsers()) && !hasExistingGuest; } boolean canCreateUser() { - return (currentUserCanCreateUsers() || anyoneCanCreateUsers()) + return mUserSwitcherEnabled + && (currentUserCanCreateUsers() || anyoneCanCreateUsers()) && mUserManager.canAddMoreUsers(UserManager.USER_TYPE_FULL_SECONDARY); } @@ -1034,8 +1045,8 @@ public class UserSwitcherController implements Dumpable { private boolean shouldUseSimpleUserSwitcher() { int defaultSimpleUserSwitcher = mContext.getResources().getBoolean( com.android.internal.R.bool.config_expandLockScreenUserSwitcher) ? 1 : 0; - return Settings.Global.getInt(mContext.getContentResolver(), - SIMPLE_USER_SWITCHER_GLOBAL_SETTING, defaultSimpleUserSwitcher) != 0; + return mGlobalSettings.getIntForUser(SIMPLE_USER_SWITCHER_GLOBAL_SETTING, + defaultSimpleUserSwitcher, UserHandle.USER_SYSTEM) != 0; } public void startActivity(Intent intent) { 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 c3268354a539..1b7353923ada 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 @@ -29,10 +29,13 @@ import com.android.systemui.statusbar.connectivity.AccessPointController; import com.android.systemui.statusbar.connectivity.AccessPointControllerImpl; import com.android.systemui.statusbar.connectivity.NetworkController; import com.android.systemui.statusbar.connectivity.NetworkControllerImpl; +import com.android.systemui.statusbar.phone.ConfigurationControllerImpl; import com.android.systemui.statusbar.policy.BluetoothController; import com.android.systemui.statusbar.policy.BluetoothControllerImpl; import com.android.systemui.statusbar.policy.CastController; import com.android.systemui.statusbar.policy.CastControllerImpl; +import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.statusbar.policy.DataSaverController; import com.android.systemui.statusbar.policy.DeviceControlsController; import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl; import com.android.systemui.statusbar.policy.DevicePostureController; @@ -85,6 +88,10 @@ public interface StatusBarPolicyModule { /** */ @Binds + ConfigurationController bindConfigurationController(ConfigurationControllerImpl impl); + + /** */ + @Binds ExtensionController provideExtensionController(ExtensionControllerImpl controllerImpl); /** */ @@ -182,4 +189,11 @@ public interface StatusBarPolicyModule { return resources.getStringArray( R.array.config_perDeviceStateRotationLockDefaults); } + + /** */ + @Provides + @SysUISingleton + static DataSaverController provideDataSaverController(NetworkController networkController) { + return networkController.getDataSaverController(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeModule.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeModule.java new file mode 100644 index 000000000000..7fa90df0e792 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeModule.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.theme; + +import android.content.res.Resources; + +import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.util.concurrency.SysUIConcurrencyModule; + +import javax.inject.Named; + +import dagger.Module; +import dagger.Provides; + +/** */ +@Module(includes = {SysUIConcurrencyModule.class}) +public class ThemeModule { + static final String LAUNCHER_PACKAGE = "theme_launcher_package"; + static final String THEME_PICKER_PACKAGE = "theme_picker_package"; + + /** */ + @Provides + @Named(LAUNCHER_PACKAGE) + static String provideLauncherPackage(@Main Resources resources) { + return resources.getString(R.string.launcher_overlayable_package); + } + + /** */ + @Provides + @Named(THEME_PICKER_PACKAGE) + static String provideThemePickerPackage(@Main Resources resources) { + return resources.getString(R.string.themepicker_overlayable_package); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java index d795d81e44bf..ba39367e290e 100644 --- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java +++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java @@ -31,6 +31,7 @@ import androidx.annotation.VisibleForTesting; import com.android.systemui.Dumpable; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dump.DumpManager; import com.google.android.collect.Lists; @@ -45,6 +46,9 @@ import java.util.Set; import java.util.concurrent.Executor; import java.util.stream.Collectors; +import javax.inject.Inject; +import javax.inject.Named; + /** * Responsible for orchestrating overlays, based on user preferences and other inputs from * {@link ThemeOverlayController}. @@ -134,17 +138,17 @@ public class ThemeOverlayApplier implements Dumpable { private final Map<String, String> mCategoryToTargetPackage = new ArrayMap<>(); private final OverlayManager mOverlayManager; private final Executor mBgExecutor; - private final Executor mMainExecutor; private final String mLauncherPackage; private final String mThemePickerPackage; + @Inject public ThemeOverlayApplier(OverlayManager overlayManager, - Executor bgExecutor, - Executor mainExecutor, - String launcherPackage, String themePickerPackage, DumpManager dumpManager) { + @Background Executor bgExecutor, + @Named(ThemeModule.LAUNCHER_PACKAGE) String launcherPackage, + @Named(ThemeModule.THEME_PICKER_PACKAGE) String themePickerPackage, + DumpManager dumpManager) { mOverlayManager = overlayManager; mBgExecutor = bgExecutor; - mMainExecutor = mainExecutor; mLauncherPackage = launcherPackage; mThemePickerPackage = themePickerPackage; mTargetPackageToCategories.put(ANDROID_PACKAGE, Sets.newHashSet( diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java index 6fdce1ae4ec2..640adcc9dd94 100644 --- a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java +++ b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java @@ -22,6 +22,12 @@ import com.android.systemui.dagger.SysUIComponent; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.SystemUIBinder; import com.android.systemui.dagger.SystemUIModule; +import com.android.systemui.statusbar.dagger.CentralSurfacesDependenciesModule; +import com.android.systemui.statusbar.notification.dagger.NotificationsModule; +import com.android.systemui.statusbar.notification.row.NotificationRowModule; + +import com.android.systemui.keyguard.dagger.KeyguardModule; +import com.android.systemui.recents.RecentsModule; import dagger.Subcomponent; @@ -30,13 +36,17 @@ import dagger.Subcomponent; */ @SysUISingleton @Subcomponent(modules = { + CentralSurfacesDependenciesModule.class, DefaultComponentBinder.class, DependencyProvider.class, - SystemUIBinder.class, + KeyguardModule.class, + NotificationRowModule.class, + NotificationsModule.class, + RecentsModule.class, SystemUIModule.class, + TvSystemUIBinder.class, TVSystemUICoreStartableModule.class, - TvSystemUIModule.class, - TvSystemUIBinder.class}) + TvSystemUIModule.class}) public interface TvSysUIComponent extends SysUIComponent { /** diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbAudioWarningDialogMessage.java b/packages/SystemUI/src/com/android/systemui/usb/UsbAudioWarningDialogMessage.java new file mode 100644 index 000000000000..e06353b3aad3 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbAudioWarningDialogMessage.java @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.usb; + +import static java.lang.annotation.RetentionPolicy.SOURCE; + +import android.annotation.IntDef; +import android.content.res.Resources; +import android.util.Log; + +import com.android.systemui.R; + +import java.lang.annotation.Retention; + +import javax.inject.Inject; + +/** + * USB Audio devices warning dialog messages help class. + */ +public class UsbAudioWarningDialogMessage { + private static final String TAG = "UsbAudioWarningDialogMessage"; + + @Retention(SOURCE) + @IntDef({TYPE_PERMISSION, TYPE_CONFIRM}) + public @interface DialogType {} + public static final int TYPE_PERMISSION = 0; + public static final int TYPE_CONFIRM = 1; + + private int mDialogType; + private UsbDialogHelper mDialogHelper; + + @Inject + public UsbAudioWarningDialogMessage() { + } + + /** + * Initialize USB audio warning dialog message type and helper class. + * @param type Dialog type for Activity. + * @param usbDialogHelper Helper class for getting USB permission and confirm dialogs + */ + public void init(@DialogType int type, UsbDialogHelper usbDialogHelper) { + mDialogType = type; + mDialogHelper = usbDialogHelper; + } + + boolean hasRecordPermission() { + return mDialogHelper.packageHasAudioRecordingPermission(); + } + + boolean isUsbAudioDevice() { + return mDialogHelper.isUsbDevice() && (mDialogHelper.deviceHasAudioCapture() + || (mDialogHelper.deviceHasAudioPlayback())); + } + + boolean hasAudioPlayback() { + return mDialogHelper.deviceHasAudioPlayback(); + } + + boolean hasAudioCapture() { + return mDialogHelper.deviceHasAudioCapture(); + } + + /** + * According to USB audio warning dialog matrix table to return warning message id. + * @return string resId for USB audio warning dialog message, otherwise {ID_NULL}. + * See usb_audio.md for USB audio Permission and Confirmation warning dialog resource + * string id matrix table. + */ + public int getMessageId() { + if (!mDialogHelper.isUsbDevice()) { + return getUsbAccessoryPromptId(); + } + + if (hasRecordPermission() && isUsbAudioDevice()) { + // case# 1, 2, 3 + return R.string.usb_audio_device_prompt; + } else if (!hasRecordPermission() && isUsbAudioDevice() && hasAudioPlayback() + && !hasAudioCapture()) { + // case# 5 + return R.string.usb_audio_device_prompt; + } + + if (!hasRecordPermission() && isUsbAudioDevice() && hasAudioCapture()) { + // case# 6,7 + return R.string.usb_audio_device_prompt_warn; + } + + Log.w(TAG, "Only shows title with empty content description!"); + return Resources.ID_NULL; + } + + /** + * Gets prompt dialog title. + * @return string id for USB prompt dialog title. + */ + public int getPromptTitleId() { + return (mDialogType == TYPE_PERMISSION) + ? R.string.usb_audio_device_permission_prompt_title + : R.string.usb_audio_device_confirm_prompt_title; + } + + /** + * Gets USB Accessory prompt message id. + * @return string id for USB Accessory prompt message. + */ + public int getUsbAccessoryPromptId() { + return (mDialogType == TYPE_PERMISSION) + ? R.string.usb_accessory_permission_prompt : R.string.usb_accessory_confirm_prompt; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java index f4558feb69aa..6e523d88a326 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java @@ -16,7 +16,10 @@ package com.android.systemui.usb; -import com.android.systemui.R; +import android.content.res.Resources; +import android.os.Bundle; + +import javax.inject.Inject; /** * Dialog shown to confirm the package to start when a USB device or accessory is attached and there @@ -24,23 +27,35 @@ import com.android.systemui.R; */ public class UsbConfirmActivity extends UsbDialogActivity { + private UsbAudioWarningDialogMessage mUsbConfirmMessageHandler; + + @Inject + public UsbConfirmActivity(UsbAudioWarningDialogMessage usbAudioWarningDialogMessage) { + mUsbConfirmMessageHandler = usbAudioWarningDialogMessage; + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + mUsbConfirmMessageHandler.init(UsbAudioWarningDialogMessage.TYPE_CONFIRM, mDialogHelper); + } + @Override protected void onResume() { super.onResume(); - final int strId; - boolean useRecordWarning = false; - if (mDialogHelper.isUsbDevice()) { - useRecordWarning = mDialogHelper.deviceHasAudioCapture() - && !mDialogHelper.packageHasAudioRecordingPermission(); - strId = useRecordWarning - ? R.string.usb_device_confirm_prompt_warn - : R.string.usb_device_confirm_prompt; - } else { - // UsbAccessory case - strId = R.string.usb_accessory_confirm_prompt; - } - setAlertParams(strId); // Only show the "always use" checkbox if there is no USB/Record warning + final boolean useRecordWarning = mDialogHelper.isUsbDevice() + && (mDialogHelper.deviceHasAudioCapture() + && !mDialogHelper.packageHasAudioRecordingPermission()); + + final int titleId = mUsbConfirmMessageHandler.getPromptTitleId(); + final String title = getString(titleId, mDialogHelper.getAppName(), + mDialogHelper.getDeviceDescription()); + final int messageId = mUsbConfirmMessageHandler.getMessageId(); + String message = (messageId != Resources.ID_NULL) + ? getString(messageId, mDialogHelper.getAppName(), + mDialogHelper.getDeviceDescription()) : null; + setAlertParams(title, message); if (!useRecordWarning) { addAlwaysUseCheckbox(); } diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDialogActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDialogActivity.java index 930bc338a918..55dec5fbe344 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/UsbDialogActivity.java +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDialogActivity.java @@ -41,7 +41,7 @@ abstract class UsbDialogActivity extends AlertActivity private TextView mClearDefaultHint; @Override - protected final void onCreate(Bundle savedInstanceState) { + protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().addSystemFlags( WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); @@ -87,11 +87,10 @@ abstract class UsbDialogActivity extends AlertActivity } } - void setAlertParams(int strId) { + void setAlertParams(String title, String message) { final AlertController.AlertParams ap = mAlertParams; - ap.mTitle = mDialogHelper.getAppName(); - ap.mMessage = getString(strId, mDialogHelper.getAppName(), - mDialogHelper.getDeviceDescription()); + ap.mTitle = title; + ap.mMessage = message; ap.mPositiveButtonText = getString(android.R.string.ok); ap.mNegativeButtonText = getString(android.R.string.cancel); ap.mPositiveButtonListener = this; diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDialogHelper.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDialogHelper.java index d63fb86ea6d4..3f061d3113be 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/UsbDialogHelper.java +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDialogHelper.java @@ -134,6 +134,13 @@ public class UsbDialogHelper { } /** + * @return True if the intent contains a UsbDevice which can play audio. + */ + public boolean deviceHasAudioPlayback() { + return mDevice != null && mDevice.getHasAudioPlayback(); + } + + /** * @return True if the package has RECORD_AUDIO permission specified in its manifest. */ public boolean packageHasAudioRecordingPermission() { @@ -272,15 +279,15 @@ public class UsbDialogHelper { return desc; } - /** - * Whether the calling package can set as default handler of the USB device or accessory. - * In case of a UsbAccessory this is the case if the calling package has an intent filter for - * {@link UsbManager#ACTION_USB_ACCESSORY_ATTACHED} with a usb-accessory filter matching the - * attached accessory. In case of a UsbDevice this is the case if the calling package has an - * intent filter for {@link UsbManager#ACTION_USB_DEVICE_ATTACHED} with a usb-device filter - * matching the attached device. - * - * @return True if the package can be default for the USB device. + /** + * Whether the calling package can set as default handler of the USB device or accessory. + * In case of a UsbAccessory this is the case if the calling package has an intent filter for + * {@link UsbManager#ACTION_USB_ACCESSORY_ATTACHED} with a usb-accessory filter matching the + * attached accessory. In case of a UsbDevice this is the case if the calling package has an + * intent filter for {@link UsbManager#ACTION_USB_DEVICE_ATTACHED} with a usb-device filter + * matching the attached device. + * + * @return True if the package can be default for the USB device. */ public boolean canBeDefault() { return mCanBeDefault; diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java index 38d634777177..9484d3a63801 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java @@ -16,7 +16,10 @@ package com.android.systemui.usb; -import com.android.systemui.R; +import android.content.res.Resources; +import android.os.Bundle; + +import javax.inject.Inject; /** * Dialog shown when a package requests access to a USB device or accessory. @@ -24,23 +27,36 @@ import com.android.systemui.R; public class UsbPermissionActivity extends UsbDialogActivity { private boolean mPermissionGranted = false; + private UsbAudioWarningDialogMessage mUsbPermissionMessageHandler; + + @Inject + public UsbPermissionActivity(UsbAudioWarningDialogMessage usbAudioWarningDialogMessage) { + mUsbPermissionMessageHandler = usbAudioWarningDialogMessage; + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + mUsbPermissionMessageHandler.init(UsbAudioWarningDialogMessage.TYPE_PERMISSION, + mDialogHelper); + } @Override protected void onResume() { super.onResume(); - final int strId; - boolean useRecordWarning = false; - if (mDialogHelper.isUsbDevice()) { - useRecordWarning = mDialogHelper.deviceHasAudioCapture() - && !mDialogHelper.packageHasAudioRecordingPermission(); - strId = useRecordWarning - ? R.string.usb_device_permission_prompt_warn - : R.string.usb_device_permission_prompt; - } else { - // UsbAccessory case - strId = R.string.usb_accessory_permission_prompt; - } - setAlertParams(strId); + final boolean useRecordWarning = mDialogHelper.isUsbDevice() + && (mDialogHelper.deviceHasAudioCapture() + && !mDialogHelper.packageHasAudioRecordingPermission()); + + final int titleId = mUsbPermissionMessageHandler.getPromptTitleId(); + final String title = getString(titleId, mDialogHelper.getAppName(), + mDialogHelper.getDeviceDescription()); + final int messageId = mUsbPermissionMessageHandler.getMessageId(); + String message = (messageId != Resources.ID_NULL) + ? getString(messageId, mDialogHelper.getAppName(), + mDialogHelper.getDeviceDescription()) : null; + setAlertParams(title, message); + // Only show the "always use" checkbox if there is no USB/Record warning if (!useRecordWarning && mDialogHelper.canBeDefault()) { addAlwaysUseCheckbox(); diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/GlobalConcurrencyModule.java b/packages/SystemUI/src/com/android/systemui/util/concurrency/GlobalConcurrencyModule.java index 107fe870a07a..323db5cfd249 100644 --- a/packages/SystemUI/src/com/android/systemui/util/concurrency/GlobalConcurrencyModule.java +++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/GlobalConcurrencyModule.java @@ -64,6 +64,15 @@ public abstract class GlobalConcurrencyModule { } /** + * @deprecated Use @Main Handler. + */ + @Deprecated + @Provides + public static Handler provideHandler() { + return new Handler(); + } + + /** * Provide a Main-Thread Executor. */ @Provides diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java b/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java index 8f61abcca4dc..8c736dc9fe70 100644 --- a/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java +++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/SysUIConcurrencyModule.java @@ -16,6 +16,8 @@ package com.android.systemui.util.concurrency; +import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME; + import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; @@ -28,6 +30,8 @@ import com.android.systemui.dagger.qualifiers.Main; import java.util.concurrent.Executor; +import javax.inject.Named; + import dagger.Module; import dagger.Provides; @@ -162,4 +166,14 @@ public abstract class SysUIConcurrencyModule { @Background DelayableExecutor executor) { return new MessageRouterImpl(executor); } + + /** */ + @Provides + @SysUISingleton + @Named(TIME_TICK_HANDLER_NAME) + public static Handler provideTimeTickHandler() { + HandlerThread thread = new HandlerThread("TimeTick"); + thread.start(); + return new Handler(thread.getLooper()); + } } diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/LeakDetector.java b/packages/SystemUI/src/com/android/systemui/util/leak/LeakDetector.java index 95e8273beded..f0e389078c2f 100644 --- a/packages/SystemUI/src/com/android/systemui/util/leak/LeakDetector.java +++ b/packages/SystemUI/src/com/android/systemui/util/leak/LeakDetector.java @@ -17,9 +17,9 @@ package com.android.systemui.util.leak; import android.os.Build; +import android.util.IndentingPrintWriter; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.IndentingPrintWriter; import com.android.systemui.Dumpable; import com.android.systemui.dump.DumpManager; @@ -133,17 +133,4 @@ public class LeakDetector implements Dumpable { pw.decreaseIndent(); pw.println(); } - - public static LeakDetector create(DumpManager dumpManager) { - if (ENABLED) { - TrackedCollections collections = new TrackedCollections(); - return new LeakDetector( - collections, - new TrackedGarbage(collections), - new TrackedObjects(collections), - dumpManager); - } else { - return new LeakDetector(null, null, null, dumpManager); - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/LeakModule.java b/packages/SystemUI/src/com/android/systemui/util/leak/LeakModule.java new file mode 100644 index 000000000000..8f5b4d6bdce9 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/util/leak/LeakModule.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.util.leak; + +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dump.DumpManager; +import com.android.systemui.util.Compile; + +import dagger.Module; +import dagger.Provides; + +/** */ +@Module +public class LeakModule { + @Provides + @SysUISingleton + LeakDetector providesLeakDetector(DumpManager dumpManager, TrackedCollections collections) { + if (Compile.IS_DEBUG) { + return new LeakDetector( + collections, + new TrackedGarbage(collections), + new TrackedObjects(collections), + dumpManager); + } else { + return new LeakDetector(null, null, null, dumpManager); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/TrackedCollections.java b/packages/SystemUI/src/com/android/systemui/util/leak/TrackedCollections.java index 5577daf7e4bf..a3e13bd8f72b 100644 --- a/packages/SystemUI/src/com/android/systemui/util/leak/TrackedCollections.java +++ b/packages/SystemUI/src/com/android/systemui/util/leak/TrackedCollections.java @@ -24,6 +24,8 @@ import java.util.Collection; import java.util.Map; import java.util.function.Predicate; +import javax.inject.Inject; + /** * Tracks the size of collections. */ @@ -34,6 +36,10 @@ public class TrackedCollections { private final WeakIdentityHashMap<Collection<?>, CollectionState> mCollections = new WeakIdentityHashMap<>(); + @Inject + TrackedCollections() { + } + /** * @see LeakDetector#trackCollection(Collection, String) */ diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java index 9b2702ff7bf2..1243c4718229 100644 --- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java +++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java @@ -215,6 +215,7 @@ public class WalletView extends FrameLayout implements WalletCardCarousel.OnCard logoView.setImageDrawable(mContext.getDrawable(R.drawable.ic_qs_plus)); mEmptyStateView.<TextView>requireViewById(R.id.empty_state_title).setText(label); mEmptyStateView.setOnClickListener(clickListener); + mAppButton.setOnClickListener(clickListener); } void showErrorMessage(@Nullable CharSequence message) { @@ -256,6 +257,11 @@ public class WalletView extends FrameLayout implements WalletCardCarousel.OnCard } @VisibleForTesting + Button getAppButton() { + return mAppButton; + } + + @VisibleForTesting TextView getErrorView() { return mErrorView; } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt index 6266bf146f5b..f8fdd8d33a57 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt @@ -29,29 +29,29 @@ import org.junit.runner.RunWith class BouncerPanelExpansionCalculatorTest : SysuiTestCase() { @Test fun testGetHostViewScaledExpansion() { - assertThat(BouncerPanelExpansionCalculator.getHostViewScaledExpansion(1f)) + assertThat(BouncerPanelExpansionCalculator.showBouncerProgress(1f)) .isEqualTo(1f) - assertThat(BouncerPanelExpansionCalculator.getHostViewScaledExpansion(0.9f)) + assertThat(BouncerPanelExpansionCalculator.showBouncerProgress(0.9f)) .isEqualTo(1f) - assertThat(BouncerPanelExpansionCalculator.getHostViewScaledExpansion(0.59f)) + assertThat(BouncerPanelExpansionCalculator.showBouncerProgress(0.59f)) .isEqualTo(0f) - assertThat(BouncerPanelExpansionCalculator.getHostViewScaledExpansion(0f)) + assertThat(BouncerPanelExpansionCalculator.showBouncerProgress(0f)) .isEqualTo(0f) assertEquals(BouncerPanelExpansionCalculator - .getHostViewScaledExpansion(0.8f), 2f / 3f, 0.01f) + .showBouncerProgress(0.8f), 2f / 3f, 0.01f) } @Test fun testGetBackScrimScaledExpansion() { - assertThat(BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(1f)) + assertThat(BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(1f)) .isEqualTo(1f) assertEquals(BouncerPanelExpansionCalculator - .getBackScrimScaledExpansion(0.95f), 1f / 2f, 0.01f) - assertThat(BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(0.9f)) + .aboutToShowBouncerProgress(0.95f), 1f / 2f, 0.01f) + assertThat(BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(0.9f)) .isEqualTo(0f) - assertThat(BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(0.5f)) + assertThat(BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(0.5f)) .isEqualTo(0f) - assertThat(BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(0f)) + assertThat(BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(0f)) .isEqualTo(0f) } @@ -63,9 +63,9 @@ class BouncerPanelExpansionCalculatorTest : SysuiTestCase() { .getKeyguardClockScaledExpansion(0.8f), 1f / 3f, 0.01f) assertThat(BouncerPanelExpansionCalculator.getKeyguardClockScaledExpansion(0.7f)) .isEqualTo(0f) - assertThat(BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(0.5f)) + assertThat(BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(0.5f)) .isEqualTo(0f) - assertThat(BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(0f)) + assertThat(BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(0f)) .isEqualTo(0f) } } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt index cc606de1b0b9..b1e2012ecd40 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt @@ -97,5 +97,6 @@ private fun faceModel(user: Int) = KeyguardFaceListenModel( primaryUser = false, scanningAllowedByStrongAuth = false, secureCameraLaunched = false, - switchingUser = false + switchingUser = false, + udfpsBouncerShowing = false ) diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java index 14c903c86b62..d49f4d8172dc 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java @@ -70,9 +70,8 @@ import java.util.ArrayList; @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper() public class KeyguardSecurityContainerTest extends SysuiTestCase { - private static final int SCREEN_WIDTH = 1600; - private static final int FAKE_MEASURE_SPEC = - View.MeasureSpec.makeMeasureSpec(SCREEN_WIDTH, View.MeasureSpec.EXACTLY); + private int mScreenWidth; + private int mFakeMeasureSpec; @Rule public MockitoRule mRule = MockitoJUnit.rule(); @@ -114,6 +113,10 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase { when(mUserSwitcherController.getKeyguardStateController()) .thenReturn(mKeyguardStateController); when(mKeyguardStateController.isShowing()).thenReturn(true); + + mScreenWidth = getUiDevice().getDisplayWidth(); + mFakeMeasureSpec = View + .MeasureSpec.makeMeasureSpec(mScreenWidth, View.MeasureSpec.EXACTLY); } @Test @@ -122,10 +125,10 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase { mUserSwitcherController); int halfWidthMeasureSpec = - View.MeasureSpec.makeMeasureSpec(SCREEN_WIDTH / 2, View.MeasureSpec.EXACTLY); - mKeyguardSecurityContainer.onMeasure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC); + View.MeasureSpec.makeMeasureSpec(mScreenWidth / 2, View.MeasureSpec.EXACTLY); + mKeyguardSecurityContainer.onMeasure(mFakeMeasureSpec, mFakeMeasureSpec); - verify(mSecurityViewFlipper).measure(halfWidthMeasureSpec, FAKE_MEASURE_SPEC); + verify(mSecurityViewFlipper).measure(halfWidthMeasureSpec, mFakeMeasureSpec); } @Test @@ -133,14 +136,16 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase { mKeyguardSecurityContainer.initMode(MODE_DEFAULT, mGlobalSettings, mFalsingManager, mUserSwitcherController); - mKeyguardSecurityContainer.measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC); - verify(mSecurityViewFlipper).measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC); + mKeyguardSecurityContainer.measure(mFakeMeasureSpec, mFakeMeasureSpec); + verify(mSecurityViewFlipper).measure(mFakeMeasureSpec, mFakeMeasureSpec); } @Test public void onMeasure_respectsViewInsets() { - int imeInsetAmount = 100; - int systemBarInsetAmount = 10; + int paddingBottom = getContext().getResources() + .getDimensionPixelSize(R.dimen.keyguard_security_view_bottom_margin); + int imeInsetAmount = paddingBottom + 1; + int systemBarInsetAmount = 0; mKeyguardSecurityContainer.initMode(MODE_DEFAULT, mGlobalSettings, mFalsingManager, mUserSwitcherController); @@ -155,17 +160,19 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase { // It's reduced by the max of the systembar and IME, so just subtract IME inset. int expectedHeightMeasureSpec = View.MeasureSpec.makeMeasureSpec( - SCREEN_WIDTH - imeInsetAmount, View.MeasureSpec.EXACTLY); + mScreenWidth - imeInsetAmount, View.MeasureSpec.EXACTLY); mKeyguardSecurityContainer.onApplyWindowInsets(insets); - mKeyguardSecurityContainer.measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC); - verify(mSecurityViewFlipper).measure(FAKE_MEASURE_SPEC, expectedHeightMeasureSpec); + mKeyguardSecurityContainer.measure(mFakeMeasureSpec, mFakeMeasureSpec); + verify(mSecurityViewFlipper).measure(mFakeMeasureSpec, expectedHeightMeasureSpec); } @Test public void onMeasure_respectsViewInsets_largerSystembar() { int imeInsetAmount = 0; - int systemBarInsetAmount = 10; + int paddingBottom = getContext().getResources() + .getDimensionPixelSize(R.dimen.keyguard_security_view_bottom_margin); + int systemBarInsetAmount = paddingBottom + 1; mKeyguardSecurityContainer.initMode(MODE_DEFAULT, mGlobalSettings, mFalsingManager, mUserSwitcherController); @@ -179,11 +186,11 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase { .build(); int expectedHeightMeasureSpec = View.MeasureSpec.makeMeasureSpec( - SCREEN_WIDTH - systemBarInsetAmount, View.MeasureSpec.EXACTLY); + mScreenWidth - systemBarInsetAmount, View.MeasureSpec.EXACTLY); mKeyguardSecurityContainer.onApplyWindowInsets(insets); - mKeyguardSecurityContainer.measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC); - verify(mSecurityViewFlipper).measure(FAKE_MEASURE_SPEC, expectedHeightMeasureSpec); + mKeyguardSecurityContainer.measure(mFakeMeasureSpec, mFakeMeasureSpec); + verify(mSecurityViewFlipper).measure(mFakeMeasureSpec, expectedHeightMeasureSpec); } private void setupForUpdateKeyguardPosition(boolean oneHandedMode) { @@ -191,8 +198,8 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase { mKeyguardSecurityContainer.initMode(mode, mGlobalSettings, mFalsingManager, mUserSwitcherController); - mKeyguardSecurityContainer.measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC); - mKeyguardSecurityContainer.layout(0, 0, SCREEN_WIDTH, SCREEN_WIDTH); + mKeyguardSecurityContainer.measure(mFakeMeasureSpec, mFakeMeasureSpec); + mKeyguardSecurityContainer.layout(0, 0, mScreenWidth, mScreenWidth); // Clear any interactions with the mock so we know the interactions definitely come from the // below testing. @@ -291,7 +298,9 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase { @Test public void testTwoOrMoreUsersDoesAllowDropDown() { // GIVEN one user has been setup - when(mUserSwitcherController.getUsers()).thenReturn(buildUserRecords(2)); + ArrayList<UserRecord> records = buildUserRecords(2); + when(mUserSwitcherController.getCurrentUserRecord()).thenReturn(records.get(0)); + when(mUserSwitcherController.getUsers()).thenReturn(records); // WHEN UserSwitcherViewMode is initialized setupUserSwitcher(); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 775addd9390b..86a4f5ad43b0 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -269,7 +269,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { mKeyguardUpdateMonitor.registerCallback(mTestCallback); mTestableLooper.processAllMessages(); - when(mAuthController.areAllAuthenticatorsRegistered()).thenReturn(true); + when(mAuthController.areAllFingerprintAuthenticatorsRegistered()).thenReturn(true); } @After @@ -499,7 +499,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { @Test public void test_doesNotTryToAuthenticateFingerprint_whenAuthenticatorsNotRegistered() { - when(mAuthController.areAllAuthenticatorsRegistered()).thenReturn(false); + when(mAuthController.areAllFingerprintAuthenticatorsRegistered()).thenReturn(false); mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */); mTestableLooper.processAllMessages(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java index 50bd9b094761..6bb994f4368a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java @@ -27,14 +27,15 @@ import static com.google.common.truth.Truth.assertThat; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; -import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -62,9 +63,11 @@ import android.util.Size; import android.view.Display; import android.view.DisplayCutout; import android.view.View; +import android.view.ViewGroup; import android.view.WindowManager; import android.view.WindowMetrics; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.test.filters.SmallTest; @@ -103,7 +106,7 @@ public class ScreenDecorationsTest extends SysuiTestCase { private SecureSettings mSecureSettings; private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock()); private FakeThreadFactory mThreadFactory; - private ArrayList<DecorProvider> mDecorProviders; + private ArrayList<DecorProvider> mPrivacyDecorProviders; @Mock private Display mDisplay; @Mock @@ -216,16 +219,43 @@ public class ScreenDecorationsTest extends SysuiTestCase { } } - private void verifyRoundedCornerViewsVisibility( + @NonNull + private int[] getRoundCornerIdsFromOverlayId(@DisplayCutout.BoundsPosition int overlayId) { + switch (overlayId) { + case BOUNDS_POSITION_LEFT: + return new int[] { + R.id.rounded_corner_top_left, + R.id.rounded_corner_top_left }; + case BOUNDS_POSITION_TOP: + return new int[] { + R.id.rounded_corner_top_left, + R.id.rounded_corner_top_right }; + case BOUNDS_POSITION_RIGHT: + return new int[] { + R.id.rounded_corner_top_right, + R.id.rounded_corner_bottom_right }; + case BOUNDS_POSITION_BOTTOM: + return new int[] { + R.id.rounded_corner_bottom_left, + R.id.rounded_corner_bottom_right }; + default: + throw new IllegalArgumentException("unknown overlayId: " + overlayId); + } + } + + private void verifyRoundedCornerViewsExist( @DisplayCutout.BoundsPosition final int overlayId, - @View.Visibility final int visibility) { + @View.Visibility final boolean isExist) { final View overlay = mScreenDecorations.mOverlays[overlayId].getRootView(); - final View left = overlay.findViewById(R.id.left); - final View right = overlay.findViewById(R.id.right); - assertNotNull(left); - assertNotNull(right); - assertThat(left.getVisibility()).isEqualTo(visibility); - assertThat(right.getVisibility()).isEqualTo(visibility); + for (int id: getRoundCornerIdsFromOverlayId(overlayId)) { + final View view = overlay.findViewById(id); + if (isExist) { + assertNotNull(view); + assertThat(view.getVisibility()).isEqualTo(View.VISIBLE); + } else { + assertNull(view); + } + } } @Nullable @@ -388,8 +418,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { mScreenDecorations.mPrivacyDotShowingListener); // Rounded corner views shall not exist - verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.GONE); - verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.GONE); + verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false); + verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false); // Privacy dots shall exist but invisible verifyDotViewsVisibility(View.INVISIBLE); @@ -417,8 +447,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE); // Rounded corner views shall exist - verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE); - verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE); + verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true); + verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true); // Privacy dots shall not exist verifyDotViewsNullable(true); @@ -447,8 +477,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { verify(mDotViewController, times(1)).setShowingListener(null); // Rounded corner views shall exist - verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE); - verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE); + verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true); + verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true); // Privacy dots shall exist but invisible verifyDotViewsVisibility(View.INVISIBLE); @@ -488,21 +518,26 @@ public class ScreenDecorationsTest extends SysuiTestCase { mScreenDecorations.start(); View leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView() - .findViewById(R.id.left); + .findViewById(R.id.rounded_corner_top_left); View rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView() - .findViewById(R.id.right); - verify(mScreenDecorations, atLeastOnce()) - .setSize(leftRoundedCorner, new Size(testTopRadius, testTopRadius)); - verify(mScreenDecorations, atLeastOnce()) - .setSize(rightRoundedCorner, new Size(testTopRadius, testTopRadius)); + .findViewById(R.id.rounded_corner_top_right); + ViewGroup.LayoutParams leftParams = leftRoundedCorner.getLayoutParams(); + ViewGroup.LayoutParams rightParams = rightRoundedCorner.getLayoutParams(); + assertEquals(leftParams.width, testTopRadius); + assertEquals(leftParams.height, testTopRadius); + assertEquals(rightParams.width, testTopRadius); + assertEquals(rightParams.height, testTopRadius); + leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView() - .findViewById(R.id.left); + .findViewById(R.id.rounded_corner_bottom_left); rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView() - .findViewById(R.id.right); - verify(mScreenDecorations, atLeastOnce()) - .setSize(leftRoundedCorner, new Size(testBottomRadius, testBottomRadius)); - verify(mScreenDecorations, atLeastOnce()) - .setSize(rightRoundedCorner, new Size(testBottomRadius, testBottomRadius)); + .findViewById(R.id.rounded_corner_bottom_right); + leftParams = leftRoundedCorner.getLayoutParams(); + rightParams = rightRoundedCorner.getLayoutParams(); + assertEquals(leftParams.width, testBottomRadius); + assertEquals(leftParams.height, testBottomRadius); + assertEquals(rightParams.width, testBottomRadius); + assertEquals(rightParams.height, testBottomRadius); } @Test @@ -518,31 +553,27 @@ public class ScreenDecorationsTest extends SysuiTestCase { .when(mScreenDecorations).getCutout(); mScreenDecorations.start(); - final Size topRadius = new Size(testTopRadius, testTopRadius); - final Size bottomRadius = new Size(testBottomRadius, testBottomRadius); - View leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView() - .findViewById(R.id.left); - boolean isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_LEFT, R.id.left); - verify(mScreenDecorations, atLeastOnce()) - .setSize(leftRoundedCorner, isTop ? topRadius : bottomRadius); - - View rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView() - .findViewById(R.id.right); - isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_LEFT, R.id.right); - verify(mScreenDecorations, atLeastOnce()) - .setSize(rightRoundedCorner, isTop ? topRadius : bottomRadius); - - leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].getRootView() - .findViewById(R.id.left); - isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_RIGHT, R.id.left); - verify(mScreenDecorations, atLeastOnce()) - .setSize(leftRoundedCorner, isTop ? topRadius : bottomRadius); - - rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].getRootView() - .findViewById(R.id.right); - isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_RIGHT, R.id.right); - verify(mScreenDecorations, atLeastOnce()) - .setSize(rightRoundedCorner, isTop ? topRadius : bottomRadius); + View topRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView() + .findViewById(R.id.rounded_corner_top_left); + View bottomRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView() + .findViewById(R.id.rounded_corner_bottom_left); + ViewGroup.LayoutParams topParams = topRoundedCorner.getLayoutParams(); + ViewGroup.LayoutParams bottomParams = bottomRoundedCorner.getLayoutParams(); + assertEquals(topParams.width, testTopRadius); + assertEquals(topParams.height, testTopRadius); + assertEquals(bottomParams.width, testBottomRadius); + assertEquals(bottomParams.height, testBottomRadius); + + topRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].getRootView() + .findViewById(R.id.rounded_corner_top_right); + bottomRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].getRootView() + .findViewById(R.id.rounded_corner_bottom_right); + topParams = topRoundedCorner.getLayoutParams(); + bottomParams = bottomRoundedCorner.getLayoutParams(); + assertEquals(topParams.width, testTopRadius); + assertEquals(topParams.height, testTopRadius); + assertEquals(bottomParams.width, testBottomRadius); + assertEquals(bottomParams.height, testBottomRadius); } @Test @@ -562,8 +593,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE); // Rounded corner views shall exist - verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE); - verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE); + verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true); + verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true); // Privacy dots shall not exist verifyDotViewsNullable(true); @@ -598,8 +629,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { verify(mDotViewController, times(1)).setShowingListener(null); // Rounded corner views shall exist - verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE); - verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE); + verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true); + verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true); // Privacy dots shall exist but invisible verifyDotViewsVisibility(View.INVISIBLE); @@ -660,10 +691,10 @@ public class ScreenDecorationsTest extends SysuiTestCase { // Top rounded corner views shall exist because of cutout // but be gone because of no rounded corner - verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.GONE); + verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false); // Bottom rounded corner views shall exist because of privacy dot // but be gone because of no rounded corner - verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.GONE); + verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false); // Privacy dots shall exist but invisible verifyDotViewsVisibility(View.INVISIBLE); @@ -691,7 +722,7 @@ public class ScreenDecorationsTest extends SysuiTestCase { // Left rounded corner views shall exist because of cutout // but be gone because of no rounded corner - verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_LEFT, View.GONE); + verifyRoundedCornerViewsExist(BOUNDS_POSITION_LEFT, false); // Top privacy dots shall not exist because of no privacy verifyDotViewsNullable(true); @@ -745,8 +776,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE); // Rounded corner views shall exist - verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE); - verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE); + verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true); + verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true); // Top privacy dots shall not exist because of no privacy dot verifyDotViewsNullable(true); @@ -775,8 +806,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { verify(mDotViewController, times(1)).setShowingListener(null); // Rounded corner views shall exist - verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE); - verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE); + verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true); + verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true); // Top privacy dots shall exist but invisible verifyDotViewsVisibility(View.INVISIBLE); @@ -914,7 +945,7 @@ public class ScreenDecorationsTest extends SysuiTestCase { verify(mDotViewController, times(2)).setShowingListener(null); // Verify each privacy dot id appears only once - mDecorProviders.stream().map(DecorProvider::getViewId).forEach(viewId -> { + mPrivacyDecorProviders.stream().map(DecorProvider::getViewId).forEach(viewId -> { int findCount = 0; for (OverlayWindow overlay: mScreenDecorations.mOverlays) { if (overlay == null) { @@ -968,8 +999,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { // Both top and bottom windows should be added with INVISIBLE because of only privacy dot, // but rounded corners visibility shall be gone because of no rounding. verifyOverlaysExistAndAdded(false, true, false, true, View.INVISIBLE); - verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.GONE); - verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.GONE); + verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false); + verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false); verify(mDotViewController, times(1)).initialize(any(), any(), any(), any()); verify(mDotViewController, times(1)).setShowingListener( mScreenDecorations.mPrivacyDotShowingListener); @@ -982,8 +1013,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { // Both top and bottom windows should be added with VISIBLE because of privacy dot and // cutout, but rounded corners visibility shall be gone because of no rounding. verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE); - verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.GONE); - verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.GONE); + verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false); + verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false); verify(mDotViewController, times(2)).initialize(any(), any(), any(), any()); verify(mDotViewController, times(1)).setShowingListener(null); } @@ -1297,6 +1328,48 @@ public class ScreenDecorationsTest extends SysuiTestCase { verify(cutoutView, times(1)).onDisplayChanged(1); } + @Test + public void testHasSameProvidersWithNullOverlays() { + setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, + 0 /* roundedPadding */, false /* multipleRadius */, + false /* fillCutout */, false /* privacyDot */); + + mScreenDecorations.start(); + + final ArrayList<DecorProvider> newProviders = new ArrayList<>(); + assertTrue(mScreenDecorations.hasSameProviders(newProviders)); + + newProviders.add(mPrivacyDotTopLeftDecorProvider); + assertFalse(mScreenDecorations.hasSameProviders(newProviders)); + + newProviders.add(mPrivacyDotTopRightDecorProvider); + assertFalse(mScreenDecorations.hasSameProviders(newProviders)); + } + + @Test + public void testHasSameProvidersWithPrivacyDots() { + setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, + 0 /* roundedPadding */, false /* multipleRadius */, + true /* fillCutout */, true /* privacyDot */); + + mScreenDecorations.start(); + + final ArrayList<DecorProvider> newProviders = new ArrayList<>(); + assertFalse(mScreenDecorations.hasSameProviders(newProviders)); + + newProviders.add(mPrivacyDotTopLeftDecorProvider); + assertFalse(mScreenDecorations.hasSameProviders(newProviders)); + + newProviders.add(mPrivacyDotTopRightDecorProvider); + assertFalse(mScreenDecorations.hasSameProviders(newProviders)); + + newProviders.add(mPrivacyDotBottomLeftDecorProvider); + assertFalse(mScreenDecorations.hasSameProviders(newProviders)); + + newProviders.add(mPrivacyDotBottomRightDecorProvider); + assertTrue(mScreenDecorations.hasSameProviders(newProviders)); + } + private void setupResources(int radius, int radiusTop, int radiusBottom, int roundedPadding, boolean multipleRadius, boolean fillCutout, boolean privacyDot) { mContext.getOrCreateTestableResources().addOverride( @@ -1336,14 +1409,14 @@ public class ScreenDecorationsTest extends SysuiTestCase { mContext.getOrCreateTestableResources().addOverride( com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, fillCutout); - mDecorProviders = new ArrayList<>(); + mPrivacyDecorProviders = new ArrayList<>(); if (privacyDot) { - mDecorProviders.add(mPrivacyDotTopLeftDecorProvider); - mDecorProviders.add(mPrivacyDotTopRightDecorProvider); - mDecorProviders.add(mPrivacyDotBottomLeftDecorProvider); - mDecorProviders.add(mPrivacyDotBottomRightDecorProvider); + mPrivacyDecorProviders.add(mPrivacyDotTopLeftDecorProvider); + mPrivacyDecorProviders.add(mPrivacyDotTopRightDecorProvider); + mPrivacyDecorProviders.add(mPrivacyDotBottomLeftDecorProvider); + mPrivacyDecorProviders.add(mPrivacyDotBottomRightDecorProvider); } - when(mPrivacyDotDecorProviderFactory.getProviders()).thenReturn(mDecorProviders); + when(mPrivacyDotDecorProviderFactory.getProviders()).thenReturn(mPrivacyDecorProviders); when(mPrivacyDotDecorProviderFactory.getHasProviders()).thenReturn(privacyDot); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java index ee150ca9db1b..18ba7dc020e2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java @@ -293,6 +293,22 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { } @Test + public void deleteWindowMagnification_notifySourceBoundsChanged() { + mInstrumentation.runOnMainSync( + () -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, + Float.NaN, + Float.NaN)); + + mInstrumentation.runOnMainSync( + () -> mWindowMagnificationController.deleteWindowMagnification()); + + // The first time is for notifying magnification enabled and the second time is for + // notifying magnification disabled. + verify(mWindowMagnifierCallback, times(2)).onSourceBoundsChanged( + (eq(mContext.getDisplayId())), any()); + } + + @Test public void moveMagnifier_schedulesFrame() { mInstrumentation.runOnMainSync(() -> { mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN, diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt index 666c9e481adc..2341928b2565 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt @@ -40,6 +40,9 @@ import com.android.internal.widget.LockPatternUtils import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.keyguard.WakefulnessLifecycle +import com.android.systemui.util.concurrency.DelayableExecutor +import com.android.systemui.util.concurrency.FakeExecutor +import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat import org.junit.After import org.junit.Rule @@ -314,7 +317,8 @@ class AuthContainerViewTest : SysuiTestCase() { wakefulnessLifecycle, userManager, lockPatternUtils, - Handler(TestableLooper.get(this).looper) + Handler(TestableLooper.get(this).looper), + FakeExecutor(FakeSystemClock()) ) if (addToView) { @@ -331,10 +335,11 @@ class AuthContainerViewTest : SysuiTestCase() { wakefulnessLifecycle: WakefulnessLifecycle, userManager: UserManager, lockPatternUtils: LockPatternUtils, - mainHandler: Handler + mainHandler: Handler, + bgExecutor: DelayableExecutor ) : AuthContainerView( config, fpProps, faceProps, - wakefulnessLifecycle, userManager, lockPatternUtils, mainHandler + wakefulnessLifecycle, userManager, lockPatternUtils, mainHandler, bgExecutor ) { override fun postOnAnimation(runnable: Runnable) { runnable.run() diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java index 190228d80cde..28da2f13eb69 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java @@ -50,6 +50,7 @@ import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricPrompt; +import android.hardware.biometrics.BiometricStateListener; import android.hardware.biometrics.ComponentInfoInternal; import android.hardware.biometrics.IBiometricContextListener; import android.hardware.biometrics.IBiometricSysuiReceiver; @@ -60,7 +61,6 @@ import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorProperties; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; -import android.hardware.fingerprint.FingerprintStateListener; import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback; import android.os.Bundle; import android.os.Handler; @@ -80,8 +80,11 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CommandQueue; +import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.concurrency.Execution; import com.android.systemui.util.concurrency.FakeExecution; +import com.android.systemui.util.concurrency.FakeExecutor; +import com.android.systemui.util.time.FakeSystemClock; import org.junit.Before; import org.junit.Rule; @@ -148,7 +151,7 @@ public class AuthControllerTest extends SysuiTestCase { @Captor ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mAuthenticatorsRegisteredCaptor; @Captor - ArgumentCaptor<FingerprintStateListener> mFingerprintStateCaptor; + ArgumentCaptor<BiometricStateListener> mBiometricStateCaptor; @Captor ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateListenerCaptor; @@ -156,6 +159,7 @@ public class AuthControllerTest extends SysuiTestCase { private Execution mExecution; private TestableLooper mTestableLooper; private Handler mHandler; + private DelayableExecutor mBackgroundExecutor; private TestableAuthController mAuthController; @Before @@ -164,6 +168,7 @@ public class AuthControllerTest extends SysuiTestCase { mExecution = new FakeExecution(); mTestableLooper = TestableLooper.get(this); mHandler = new Handler(mTestableLooper.getLooper()); + mBackgroundExecutor = new FakeExecutor(new FakeSystemClock()); when(mContextSpy.getPackageManager()).thenReturn(mPackageManager); when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)) @@ -221,7 +226,7 @@ public class AuthControllerTest extends SysuiTestCase { // Callback tests @Test - public void testRegistersFingerprintStateListener_afterAllAuthenticatorsAreRegistered() + public void testRegistersBiometricStateListener_afterAllAuthenticatorsAreRegistered() throws RemoteException { // This test is sensitive to prior FingerprintManager interactions. reset(mFingerprintManager); @@ -237,12 +242,12 @@ public class AuthControllerTest extends SysuiTestCase { mAuthenticatorsRegisteredCaptor.capture()); mTestableLooper.processAllMessages(); - verify(mFingerprintManager, never()).registerFingerprintStateListener(any()); + verify(mFingerprintManager, never()).registerBiometricStateListener(any()); mAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(new ArrayList<>()); mTestableLooper.processAllMessages(); - verify(mFingerprintManager).registerFingerprintStateListener(any()); + verify(mFingerprintManager).registerBiometricStateListener(any()); } @Test @@ -264,11 +269,11 @@ public class AuthControllerTest extends SysuiTestCase { mAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(new ArrayList<>()); mTestableLooper.processAllMessages(); - verify(mFingerprintManager).registerFingerprintStateListener( - mFingerprintStateCaptor.capture()); + verify(mFingerprintManager).registerBiometricStateListener( + mBiometricStateCaptor.capture()); // Enrollments changed for an unknown sensor. - mFingerprintStateCaptor.getValue().onEnrollmentsChanged(0 /* userId */, + mBiometricStateCaptor.getValue().onEnrollmentsChanged(0 /* userId */, 0xbeef /* sensorId */, true /* hasEnrollments */); mTestableLooper.processAllMessages(); @@ -759,11 +764,12 @@ public class AuthControllerTest extends SysuiTestCase { super(context, execution, commandQueue, activityTaskManager, windowManager, fingerprintManager, faceManager, udfpsControllerFactory, sidefpsControllerFactory, mDisplayManager, mWakefulnessLifecycle, - mUserManager, mLockPatternUtils, statusBarStateController, mHandler); + mUserManager, mLockPatternUtils, statusBarStateController, mHandler, + mBackgroundExecutor); } @Override - protected AuthDialog buildDialog(PromptInfo promptInfo, + protected AuthDialog buildDialog(DelayableExecutor bgExecutor, PromptInfo promptInfo, boolean requireConfirmation, int userId, int[] sensorIds, String opPackageName, boolean skipIntro, long operationId, long requestId, @BiometricManager.BiometricMultiSensorMode int multiSensorConfig, diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java index 05cf6a50eda0..5d624cdc47a1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java @@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.inOrder; @@ -183,6 +184,8 @@ public class UdfpsControllerTest extends SysuiTestCase { private SystemUIDialogManager mSystemUIDialogManager; @Mock private ActivityLaunchAnimator mActivityLaunchAnimator; + @Mock + private AlternateUdfpsTouchProvider mTouchProvider; // Capture listeners so that they can be used to send events @Captor private ArgumentCaptor<IUdfpsOverlayController> mOverlayCaptor; @@ -256,7 +259,8 @@ public class UdfpsControllerTest extends SysuiTestCase { mUnlockedScreenOffAnimationController, mSystemUIDialogManager, mLatencyTracker, - mActivityLaunchAnimator); + mActivityLaunchAnimator, + Optional.of(mTouchProvider)); verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture()); mOverlayController = mOverlayCaptor.getValue(); verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture()); @@ -418,9 +422,10 @@ public class UdfpsControllerTest extends SysuiTestCase { mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); moveEvent.recycle(); // THEN FingerprintManager is notified about onPointerDown - verify(mFingerprintManager).onPointerDown(eq(TEST_REQUEST_ID), - eq(mUdfpsController.mSensorProps.sensorId), + verify(mTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(0), eq(0), eq(0f), eq(0f)); + verify(mFingerprintManager, never()).onPointerDown(anyLong(), anyInt(), anyInt(), anyInt(), + anyFloat(), anyFloat()); verify(mLatencyTracker).onActionStart(eq(LatencyTracker.ACTION_UDFPS_ILLUMINATE)); // AND illumination begins verify(mUdfpsView).startIllumination(mOnIlluminatedRunnableCaptor.capture()); @@ -447,9 +452,10 @@ public class UdfpsControllerTest extends SysuiTestCase { // AND onIlluminatedRunnable that notifies FingerprintManager is set verify(mUdfpsView).startIllumination(mOnIlluminatedRunnableCaptor.capture()); mOnIlluminatedRunnableCaptor.getValue().run(); - verify(mFingerprintManager).onPointerDown(eq(TEST_REQUEST_ID), - eq(mUdfpsController.mSensorProps.sensorId), + verify(mTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(0), eq(0), eq(3f) /* minor */, eq(2f) /* major */); + verify(mFingerprintManager, never()).onPointerDown(anyLong(), anyInt(), anyInt(), anyInt(), + anyFloat(), anyFloat()); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java index 186f2bb1d127..cd05ad496cc8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java @@ -124,7 +124,7 @@ public class UdfpsKeyguardViewControllerTest extends SysuiTestCase { when(mView.getContext()).thenReturn(mResourceContext); when(mResourceContext.getString(anyInt())).thenReturn("test string"); when(mKeyguardViewMediator.isAnimatingScreenOff()).thenReturn(false); - when(mView.getDialogSuggestedAlpha()).thenReturn(1f); + when(mView.getUnpausedAlpha()).thenReturn(255); mController = new UdfpsKeyguardViewController( mView, mStatusBarStateController, @@ -205,17 +205,18 @@ public class UdfpsKeyguardViewControllerTest extends SysuiTestCase { captureAltAuthInterceptor(); when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(true); + when(mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()).thenReturn(true); mAltAuthInterceptor.onBouncerVisibilityChanged(); assertTrue(mController.shouldPauseAuth()); } @Test - public void testShouldPauseAuthDialogSuggestedAlpha0() { + public void testShouldPauseAuthUnpausedAlpha0() { mController.onViewAttached(); captureStatusBarStateListeners(); - when(mView.getDialogSuggestedAlpha()).thenReturn(0f); + when(mView.getUnpausedAlpha()).thenReturn(0); sendStatusBarStateChanged(StatusBarState.KEYGUARD); assertTrue(mController.shouldPauseAuth()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/ActionReceiverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/ActionReceiverTest.kt index e95eb4ef6509..f5990be8e0c3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/ActionReceiverTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/ActionReceiverTest.kt @@ -42,6 +42,7 @@ import org.mockito.ArgumentMatchers.anyString import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito +import org.mockito.Mockito.`when` import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.verify @@ -81,6 +82,8 @@ class ActionReceiverTest : SysuiTestCase() { @Mock private lateinit var unregisterFunction: BroadcastReceiver.() -> Unit @Mock + private lateinit var isPendingRemovalFunction: (BroadcastReceiver, Int) -> Boolean + @Mock private lateinit var receiver1: BroadcastReceiver @Mock private lateinit var receiver2: BroadcastReceiver @@ -98,13 +101,16 @@ class ActionReceiverTest : SysuiTestCase() { MockitoAnnotations.initMocks(this) executor = FakeExecutor(FakeSystemClock()) + `when`(isPendingRemovalFunction(any(), anyInt())).thenReturn(false) + actionReceiver = ActionReceiver( ACTION1, USER.identifier, registerFunction, unregisterFunction, executor, - logger + logger, + isPendingRemovalFunction ) } @@ -249,6 +255,20 @@ class ActionReceiverTest : SysuiTestCase() { verify(logger).logBroadcastDispatched(anyInt(), eq(ACTION1), sameNotNull(receiver1)) } + @Test + fun testBroadcastNotDispatchingOnPendingRemoval() { + `when`(isPendingRemovalFunction(receiver1, USER.identifier)).thenReturn(true) + + val receiverData = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER) + + actionReceiver.addReceiverData(receiverData) + + val intent = Intent(ACTION1) + actionReceiver.onReceive(mContext, intent) + executor.runAllReady() + verify(receiver1, never()).onReceive(any(), eq(intent)) + } + @Test(expected = IllegalStateException::class) fun testBroadcastWithWrongAction_throwsException() { actionReceiver.onReceive(mContext, Intent(ACTION2)) diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt index a1d19332b537..7795d2caf091 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt @@ -41,6 +41,8 @@ import org.mockito.ArgumentCaptor import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito.`when` +import org.mockito.Mockito.anyInt +import org.mockito.Mockito.inOrder import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.verify @@ -85,6 +87,8 @@ class BroadcastDispatcherTest : SysuiTestCase() { private lateinit var logger: BroadcastDispatcherLogger @Mock private lateinit var userTracker: UserTracker + @Mock + private lateinit var removalPendingStore: PendingRemovalStore private lateinit var executor: Executor @@ -108,6 +112,7 @@ class BroadcastDispatcherTest : SysuiTestCase() { mock(DumpManager::class.java), logger, userTracker, + removalPendingStore, mapOf(0 to mockUBRUser0, 1 to mockUBRUser1)) // These should be valid filters @@ -325,6 +330,57 @@ class BroadcastDispatcherTest : SysuiTestCase() { broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter) } + @Test + fun testTaggedReceiverForRemovalImmediately_allUsers() { + broadcastDispatcher.unregisterReceiver(broadcastReceiver) + + verify(removalPendingStore).tagForRemoval(broadcastReceiver, UserHandle.USER_ALL) + verify(removalPendingStore, never()).clearPendingRemoval(eq(broadcastReceiver), anyInt()) + } + + @Test + fun testTaggedReceiverForRemovalImmediately_singleUser() { + val user = 0 + broadcastDispatcher.unregisterReceiverForUser(broadcastReceiver, UserHandle.of(user)) + + verify(removalPendingStore).tagForRemoval(broadcastReceiver, user) + verify(removalPendingStore, never()).clearPendingRemoval(eq(broadcastReceiver), anyInt()) + } + + @Test + fun testUnregisterReceiverClearsPendingRemovalAfterRemoving_allUsers() { + broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, null, user0) + broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, null, user1) + + broadcastDispatcher.unregisterReceiver(broadcastReceiver) + + testableLooper.processAllMessages() + + val inOrderUser0 = inOrder(mockUBRUser0, removalPendingStore) + inOrderUser0.verify(mockUBRUser0).unregisterReceiver(broadcastReceiver) + inOrderUser0.verify(removalPendingStore) + .clearPendingRemoval(broadcastReceiver, UserHandle.USER_ALL) + + val inOrderUser1 = inOrder(mockUBRUser1, removalPendingStore) + inOrderUser1.verify(mockUBRUser1).unregisterReceiver(broadcastReceiver) + inOrderUser1.verify(removalPendingStore) + .clearPendingRemoval(broadcastReceiver, UserHandle.USER_ALL) + } + + @Test + fun testUnregisterReceiverclearPendingRemovalAfterRemoving_singleUser() { + broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, null, user1) + + broadcastDispatcher.unregisterReceiverForUser(broadcastReceiver, user1) + + testableLooper.processAllMessages() + + val inOrderUser1 = inOrder(mockUBRUser1, removalPendingStore) + inOrderUser1.verify(mockUBRUser1).unregisterReceiver(broadcastReceiver) + inOrderUser1.verify(removalPendingStore) + .clearPendingRemoval(broadcastReceiver, user1.identifier) + } + private fun setUserMock(mockContext: Context, user: UserHandle) { `when`(mockContext.user).thenReturn(user) `when`(mockContext.userId).thenReturn(user.identifier) @@ -337,8 +393,17 @@ class BroadcastDispatcherTest : SysuiTestCase() { dumpManager: DumpManager, logger: BroadcastDispatcherLogger, userTracker: UserTracker, + removalPendingStore: PendingRemovalStore, var mockUBRMap: Map<Int, UserBroadcastDispatcher> - ) : BroadcastDispatcher(context, bgLooper, executor, dumpManager, logger, userTracker) { + ) : BroadcastDispatcher( + context, + bgLooper, + executor, + dumpManager, + logger, + userTracker, + removalPendingStore + ) { override fun createUBRForUser(userId: Int): UserBroadcastDispatcher { return mockUBRMap.getOrDefault(userId, mock(UserBroadcastDispatcher::class.java)) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt index 141b3b446c01..53dcc8d269c9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt @@ -37,7 +37,8 @@ class FakeBroadcastDispatcher( dumpManager: DumpManager, logger: BroadcastDispatcherLogger, userTracker: UserTracker -) : BroadcastDispatcher(context, looper, executor, dumpManager, logger, userTracker) { +) : BroadcastDispatcher( + context, looper, executor, dumpManager, logger, userTracker, PendingRemovalStore(logger)) { private val registeredReceivers = ArraySet<BroadcastReceiver>() diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/PendingRemovalStoreTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/PendingRemovalStoreTest.kt new file mode 100644 index 000000000000..43d2cb8be2d6 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/PendingRemovalStoreTest.kt @@ -0,0 +1,81 @@ +package com.android.systemui.broadcast + +import android.content.BroadcastReceiver +import android.os.UserHandle +import android.testing.AndroidTestingRunner +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@RunWith(AndroidTestingRunner::class) +@SmallTest +class PendingRemovalStoreTest : SysuiTestCase() { + + @Mock + private lateinit var logger: BroadcastDispatcherLogger + @Mock + private lateinit var receiverOne: BroadcastReceiver + @Mock + private lateinit var receiverTwo: BroadcastReceiver + + private lateinit var store: PendingRemovalStore + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + + store = PendingRemovalStore(logger) + } + + @Test + fun testTagForRemoval_logged() { + val user = 10 + store.tagForRemoval(receiverOne, 10) + + verify(logger).logTagForRemoval(user, receiverOne) + } + + @Test + fun testClearedPendingRemoval_logged() { + val user = UserHandle.USER_ALL + store.clearPendingRemoval(receiverOne, user) + + verify(logger).logClearedAfterRemoval(user, receiverOne) + } + + @Test + fun testTaggedReceiverMarkedAsPending_specificUser() { + val user = 10 + store.tagForRemoval(receiverOne, user) + + assertThat(store.isPendingRemoval(receiverOne, user)).isTrue() + assertThat(store.isPendingRemoval(receiverOne, user + 1)).isFalse() + assertThat(store.isPendingRemoval(receiverOne, UserHandle.USER_ALL)).isFalse() + } + + @Test + fun testTaggedReceiverMarkedAsPending_allUsers() { + val user = 10 + store.tagForRemoval(receiverOne, UserHandle.USER_ALL) + + assertThat(store.isPendingRemoval(receiverOne, user)).isTrue() + assertThat(store.isPendingRemoval(receiverOne, user + 1)).isTrue() + assertThat(store.isPendingRemoval(receiverOne, UserHandle.USER_ALL)).isTrue() + } + + @Test + fun testOnlyBlockCorrectReceiver() { + val user = 10 + store.tagForRemoval(receiverOne, user) + + assertThat(store.isPendingRemoval(receiverOne, user)).isTrue() + assertThat(store.isPendingRemoval(receiverTwo, user)).isFalse() + } +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt index 116b81d4d5ca..39e4467bd84f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt @@ -68,6 +68,8 @@ class UserBroadcastDispatcherTest : SysuiTestCase() { private lateinit var mockContext: Context @Mock private lateinit var logger: BroadcastDispatcherLogger + @Mock + private lateinit var removalPendingStore: PendingRemovalStore private lateinit var testableLooper: TestableLooper private lateinit var userBroadcastDispatcher: UserBroadcastDispatcher @@ -84,7 +86,13 @@ class UserBroadcastDispatcherTest : SysuiTestCase() { fakeExecutor = FakeExecutor(FakeSystemClock()) userBroadcastDispatcher = object : UserBroadcastDispatcher( - mockContext, USER_ID, testableLooper.looper, mock(Executor::class.java), logger) { + mockContext, + USER_ID, + testableLooper.looper, + mock(Executor::class.java), + logger, + removalPendingStore + ) { override fun createActionReceiver( action: String, permission: String?, @@ -216,7 +224,8 @@ class UserBroadcastDispatcherTest : SysuiTestCase() { USER_ID, testableLooper.looper, fakeExecutor, - logger + logger, + removalPendingStore ) uBR.registerReceiver( ReceiverData( @@ -243,7 +252,8 @@ class UserBroadcastDispatcherTest : SysuiTestCase() { USER_ID, testableLooper.looper, fakeExecutor, - logger + logger, + removalPendingStore ) uBR.registerReceiver( ReceiverData( diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt index ca74df0a23c5..69366fa0d4a9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt @@ -19,25 +19,19 @@ package com.android.systemui.decor import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.DisplayCutout -import android.view.LayoutInflater import android.view.Surface import android.view.View -import android.view.ViewGroup import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase -import com.android.systemui.util.mockito.eq import org.junit.Assert import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.mockito.Mock -import org.mockito.Mockito -import org.mockito.Mockito.anyInt +import org.mockito.Mockito.never import org.mockito.Mockito.spy +import org.mockito.Mockito.times import org.mockito.Mockito.verify -import org.mockito.MockitoAnnotations -import org.mockito.Mockito.`when` as whenever @RunWith(AndroidTestingRunner::class) @RunWithLooper(setAsMainLooper = true) @@ -45,62 +39,144 @@ import org.mockito.Mockito.`when` as whenever class OverlayWindowTest : SysuiTestCase() { companion object { - private val TEST_DECOR_VIEW_ID = R.id.privacy_dot_bottom_right_container - private val TEST_DECOR_LAYOUT_ID = R.layout.privacy_dot_bottom_right + private val TEST_DECOR_VIEW_ID_1 = R.id.privacy_dot_top_left_container + private val TEST_DECOR_VIEW_ID_2 = R.id.privacy_dot_bottom_left_container + private val TEST_DECOR_VIEW_ID_3 = R.id.privacy_dot_bottom_right_container } private lateinit var overlay: OverlayWindow - - @Mock private lateinit var layoutInflater: LayoutInflater - @Mock private lateinit var decorProvider: DecorProvider + private lateinit var decorProvider1: DecorProvider + private lateinit var decorProvider2: DecorProvider + private lateinit var decorProvider3: DecorProvider @Before fun setUp() { - MockitoAnnotations.initMocks(this) - - layoutInflater = spy(LayoutInflater.from(mContext)) - - overlay = OverlayWindow(layoutInflater, DisplayCutout.BOUNDS_POSITION_RIGHT) - - whenever(decorProvider.viewId).thenReturn(TEST_DECOR_VIEW_ID) - whenever(decorProvider.inflateView( - eq(layoutInflater), - eq(overlay.rootView), - anyInt()) - ).then { - val layoutInflater = it.getArgument<LayoutInflater>(0) - val parent = it.getArgument<ViewGroup>(1) - layoutInflater.inflate(TEST_DECOR_LAYOUT_ID, parent) - return@then parent.getChildAt(parent.childCount - 1) - } - } + decorProvider1 = spy(PrivacyDotCornerDecorProviderImpl( + viewId = TEST_DECOR_VIEW_ID_1, + alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP, + alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT, + layoutId = R.layout.privacy_dot_top_left)) + decorProvider2 = spy(PrivacyDotCornerDecorProviderImpl( + viewId = TEST_DECOR_VIEW_ID_2, + alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM, + alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT, + layoutId = R.layout.privacy_dot_bottom_left)) + decorProvider3 = spy(PrivacyDotCornerDecorProviderImpl( + viewId = TEST_DECOR_VIEW_ID_3, + alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM, + alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT, + layoutId = R.layout.privacy_dot_bottom_right)) - @Test - fun testAnyBoundsPositionShallNoExceptionForConstructor() { - OverlayWindow(layoutInflater, DisplayCutout.BOUNDS_POSITION_LEFT) - OverlayWindow(layoutInflater, DisplayCutout.BOUNDS_POSITION_TOP) - OverlayWindow(layoutInflater, DisplayCutout.BOUNDS_POSITION_RIGHT) - OverlayWindow(layoutInflater, DisplayCutout.BOUNDS_POSITION_BOTTOM) + overlay = OverlayWindow(mContext) } @Test fun testAddProvider() { @Surface.Rotation val rotation = Surface.ROTATION_270 - overlay.addDecorProvider(decorProvider, rotation) - verify(decorProvider, Mockito.times(1)).inflateView( - eq(layoutInflater), eq(overlay.rootView), eq(rotation)) - val viewFoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID) - Assert.assertNotNull(viewFoundFromRootView) - Assert.assertEquals(viewFoundFromRootView, overlay.getView(TEST_DECOR_VIEW_ID)) + overlay.addDecorProvider(decorProvider1, rotation) + overlay.addDecorProvider(decorProvider2, rotation) + + verify(decorProvider1, times(1)).inflateView( + mContext, overlay.rootView, rotation) + verify(decorProvider2, times(1)).inflateView( + mContext, overlay.rootView, rotation) + + val view1FoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID_1) + Assert.assertNotNull(view1FoundFromRootView) + Assert.assertEquals(view1FoundFromRootView, overlay.getView(TEST_DECOR_VIEW_ID_1)) + val view2FoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID_2) + Assert.assertNotNull(view2FoundFromRootView) + Assert.assertEquals(view2FoundFromRootView, overlay.getView(TEST_DECOR_VIEW_ID_2)) } @Test fun testRemoveView() { - @Surface.Rotation val rotation = Surface.ROTATION_270 - overlay.addDecorProvider(decorProvider, rotation) - overlay.removeView(TEST_DECOR_VIEW_ID) - val viewFoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID) + overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270) + overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270) + overlay.removeView(TEST_DECOR_VIEW_ID_1) + + val viewFoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID_1) Assert.assertNull(viewFoundFromRootView) - Assert.assertNull(overlay.getView(TEST_DECOR_LAYOUT_ID)) + Assert.assertNull(overlay.getView(TEST_DECOR_VIEW_ID_1)) + } + + @Test + fun testOnReloadResAndMeasureWithoutIds() { + overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0) + overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0) + + overlay.onReloadResAndMeasure( + reloadToken = 1, + rotation = Surface.ROTATION_90, + displayUniqueId = null) + verify(decorProvider1, times(1)).onReloadResAndMeasure( + overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, null) + verify(decorProvider2, times(1)).onReloadResAndMeasure( + overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, null) + } + + @Test + fun testOnReloadResAndMeasureWithIds() { + overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0) + overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0) + + overlay.onReloadResAndMeasure( + filterIds = arrayOf(TEST_DECOR_VIEW_ID_2), + reloadToken = 1, + rotation = Surface.ROTATION_90, + displayUniqueId = null) + verify(decorProvider1, never()).onReloadResAndMeasure( + overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, null) + verify(decorProvider2, times(1)).onReloadResAndMeasure( + overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, null) + } + + @Test + fun testRemoveRedundantViewsWithNullParameter() { + overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270) + overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270) + + overlay.removeRedundantViews(null) + + Assert.assertNull(overlay.getView(TEST_DECOR_VIEW_ID_1)) + Assert.assertNull(overlay.rootView.findViewById(TEST_DECOR_VIEW_ID_1)) + Assert.assertNull(overlay.getView(TEST_DECOR_VIEW_ID_2)) + Assert.assertNull(overlay.rootView.findViewById(TEST_DECOR_VIEW_ID_2)) + } + + @Test + fun testRemoveRedundantViewsWith2Providers() { + overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270) + overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270) + + overlay.removeRedundantViews(IntArray(2).apply { + this[0] = TEST_DECOR_VIEW_ID_3 + this[1] = TEST_DECOR_VIEW_ID_1 + }) + + Assert.assertNotNull(overlay.getView(TEST_DECOR_VIEW_ID_1)) + Assert.assertNotNull(overlay.rootView.findViewById(TEST_DECOR_VIEW_ID_1)) + Assert.assertNull(overlay.getView(TEST_DECOR_VIEW_ID_2)) + Assert.assertNull(overlay.rootView.findViewById(TEST_DECOR_VIEW_ID_2)) + } + + @Test + fun testHasSameProviders() { + Assert.assertTrue(overlay.hasSameProviders(emptyList())) + Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider1))) + Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2))) + Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2, decorProvider1))) + + overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0) + Assert.assertFalse(overlay.hasSameProviders(emptyList())) + Assert.assertTrue(overlay.hasSameProviders(listOf(decorProvider1))) + Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2))) + Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2, decorProvider1))) + + overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0) + Assert.assertFalse(overlay.hasSameProviders(emptyList())) + Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider1))) + Assert.assertFalse(overlay.hasSameProviders(listOf(decorProvider2))) + Assert.assertTrue(overlay.hasSameProviders(listOf(decorProvider2, decorProvider1))) } }
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt index bac08176d2eb..171b76748d26 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt @@ -18,7 +18,6 @@ package com.android.systemui.decor import android.content.res.Resources import android.testing.AndroidTestingRunner -import android.testing.TestableLooper.RunWithLooper import android.view.DisplayCutout import androidx.test.filters.SmallTest import com.android.systemui.R @@ -32,7 +31,6 @@ import org.mockito.Mockito.spy import org.mockito.Mockito.`when` as whenever @RunWith(AndroidTestingRunner::class) -@RunWithLooper(setAsMainLooper = true) @SmallTest class PrivacyDotDecorProviderFactoryTest : SysuiTestCase() { private lateinit var mPrivacyDotDecorProviderFactory: PrivacyDotDecorProviderFactory diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerDecorProviderFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerDecorProviderFactoryTest.kt new file mode 100644 index 000000000000..621bcf69bb03 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerDecorProviderFactoryTest.kt @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.decor + +import android.testing.AndroidTestingRunner +import android.util.Size +import android.view.DisplayCutout +import androidx.test.filters.SmallTest +import com.android.systemui.R +import com.android.systemui.SysuiTestCase +import org.junit.Assert +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito +import org.mockito.Mockito.spy + +@RunWith(AndroidTestingRunner::class) +@SmallTest +class RoundedCornerDecorProviderFactoryTest : SysuiTestCase() { + + @Mock private lateinit var roundedCornerResDelegate: RoundedCornerResDelegate + private lateinit var roundedCornerDecorProviderFactory: RoundedCornerDecorProviderFactory + + @Before + fun setUp() { + roundedCornerResDelegate = spy(RoundedCornerResDelegate(mContext.resources, null)) + } + + @Test + fun testNoRoundedCorners() { + Mockito.doReturn(Size(0, 0)).`when`(roundedCornerResDelegate).topRoundedSize + Mockito.doReturn(Size(0, 0)).`when`(roundedCornerResDelegate).bottomRoundedSize + Mockito.doReturn(false).`when`(roundedCornerResDelegate).isMultipleRadius + + roundedCornerDecorProviderFactory = + RoundedCornerDecorProviderFactory(roundedCornerResDelegate) + + Assert.assertEquals(false, roundedCornerDecorProviderFactory.hasProviders) + Assert.assertEquals(0, roundedCornerDecorProviderFactory.providers.size) + } + + @Test + fun testHasRoundedCornersIfTopWidthLargerThan0() { + Mockito.doReturn(Size(1, 0)).`when`(roundedCornerResDelegate).topRoundedSize + Mockito.doReturn(Size(0, 0)).`when`(roundedCornerResDelegate).bottomRoundedSize + Mockito.doReturn(false).`when`(roundedCornerResDelegate).isMultipleRadius + + roundedCornerDecorProviderFactory = + RoundedCornerDecorProviderFactory(roundedCornerResDelegate) + + Assert.assertEquals(true, roundedCornerDecorProviderFactory.hasProviders) + roundedCornerDecorProviderFactory.providers.let { providers -> + Assert.assertEquals(2, providers.size) + Assert.assertEquals(1, providers.count { + ((it.viewId == R.id.rounded_corner_top_left) + and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP) + and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_LEFT)) + }) + Assert.assertEquals(1, providers.count { + ((it.viewId == R.id.rounded_corner_top_right) + and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP) + and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_RIGHT)) + }) + } + } + + @Test + fun testHasRoundedCornersIfBottomWidthLargerThan0() { + Mockito.doReturn(Size(0, 0)).`when`(roundedCornerResDelegate).topRoundedSize + Mockito.doReturn(Size(1, 1)).`when`(roundedCornerResDelegate).bottomRoundedSize + Mockito.doReturn(false).`when`(roundedCornerResDelegate).isMultipleRadius + + roundedCornerDecorProviderFactory = + RoundedCornerDecorProviderFactory(roundedCornerResDelegate) + + Assert.assertEquals(true, roundedCornerDecorProviderFactory.hasProviders) + roundedCornerDecorProviderFactory.providers.let { providers -> + Assert.assertEquals(2, providers.size) + Assert.assertEquals(1, providers.count { + ((it.viewId == R.id.rounded_corner_bottom_left) + and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_BOTTOM) + and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_LEFT)) + }) + Assert.assertEquals(1, providers.count { + ((it.viewId == R.id.rounded_corner_bottom_right) + and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_BOTTOM) + and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_RIGHT)) + }) + } + } + + @Test + fun test4CornerDecorProvidersInfo() { + Mockito.doReturn(Size(10, 10)).`when`(roundedCornerResDelegate).topRoundedSize + Mockito.doReturn(Size(10, 10)).`when`(roundedCornerResDelegate).bottomRoundedSize + Mockito.doReturn(true).`when`(roundedCornerResDelegate).isMultipleRadius + + roundedCornerDecorProviderFactory = + RoundedCornerDecorProviderFactory(roundedCornerResDelegate) + + Assert.assertEquals(true, roundedCornerDecorProviderFactory.hasProviders) + roundedCornerDecorProviderFactory.providers.let { providers -> + Assert.assertEquals(4, providers.size) + Assert.assertEquals(1, providers.count { + ((it.viewId == R.id.rounded_corner_top_left) + and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP) + and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_LEFT)) + }) + Assert.assertEquals(1, providers.count { + ((it.viewId == R.id.rounded_corner_top_right) + and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP) + and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_RIGHT)) + }) + Assert.assertEquals(1, providers.count { + ((it.viewId == R.id.rounded_corner_bottom_left) + and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_BOTTOM) + and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_LEFT)) + }) + Assert.assertEquals(1, providers.count { + ((it.viewId == R.id.rounded_corner_bottom_right) + and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_BOTTOM) + and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_RIGHT)) + }) + } + } +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt index 2effaec58a86..1fec38018f51 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt @@ -45,7 +45,7 @@ class RoundedCornerResDelegateTest : SysuiTestCase() { } @Test - fun testReloadAllAndDefaultRadius() { + fun testUpdateDisplayUniqueId() { mContext.orCreateTestableResources.addOverrides( mockTypeArray = mockTypedArray, radius = 3, @@ -65,7 +65,34 @@ class RoundedCornerResDelegateTest : SysuiTestCase() { radiusTop = 6, radiusBottom = 0) - roundedCornerResDelegate.reloadAll("test") + roundedCornerResDelegate.updateDisplayUniqueId("test", null) + + assertEquals(Size(6, 6), roundedCornerResDelegate.topRoundedSize) + assertEquals(Size(5, 5), roundedCornerResDelegate.bottomRoundedSize) + } + + @Test + fun testNotUpdateDisplayUniqueIdButChangeRefreshToken() { + mContext.orCreateTestableResources.addOverrides( + mockTypeArray = mockTypedArray, + radius = 3, + radiusTop = 0, + radiusBottom = 4, + multipleRadius = false) + + roundedCornerResDelegate = RoundedCornerResDelegate(mContext.resources, null) + + assertEquals(Size(3, 3), roundedCornerResDelegate.topRoundedSize) + assertEquals(Size(4, 4), roundedCornerResDelegate.bottomRoundedSize) + assertEquals(false, roundedCornerResDelegate.isMultipleRadius) + + mContext.orCreateTestableResources.addOverrides( + mockTypeArray = mockTypedArray, + radius = 5, + radiusTop = 6, + radiusBottom = 0) + + roundedCornerResDelegate.updateDisplayUniqueId(null, 1) assertEquals(Size(6, 6), roundedCornerResDelegate.topRoundedSize) assertEquals(Size(5, 5), roundedCornerResDelegate.bottomRoundedSize) @@ -82,11 +109,21 @@ class RoundedCornerResDelegateTest : SysuiTestCase() { roundedCornerResDelegate = RoundedCornerResDelegate(mContext.resources, null) val factor = 5 - roundedCornerResDelegate.updateTuningSizeFactor(factor) + roundedCornerResDelegate.updateTuningSizeFactor(factor, 1) val length = (factor * mContext.resources.displayMetrics.density).toInt() assertEquals(Size(length, length), roundedCornerResDelegate.topRoundedSize) assertEquals(Size(length, length), roundedCornerResDelegate.bottomRoundedSize) + + mContext.orCreateTestableResources.addOverrides( + mockTypeArray = mockTypedArray, + radiusTop = 1, + radiusBottom = 2, + multipleRadius = false) + roundedCornerResDelegate.updateTuningSizeFactor(null, 2) + + assertEquals(Size(1, 1), roundedCornerResDelegate.topRoundedSize) + assertEquals(Size(2, 2), roundedCornerResDelegate.bottomRoundedSize) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java index 4736587e6955..2e7b88d5fd38 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java @@ -506,7 +506,7 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { } @Test - public void transitionToAodPaused_resetsToDefaultBrightness_lightSensorDisabled() { + public void transitionToAodPaused_lightSensorDisabled() { // GIVEN AOD mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); @@ -516,9 +516,6 @@ public class DozeScreenBrightnessTest extends SysuiTestCase { mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSED); waitForSensorManager(); - // THEN brightness is reset and light sensor is unregistered - assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS); - // THEN new light events don't update brightness since the light sensor was unregistered mSensor.sendSensorEvent(1); assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS); diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java index 6453c204342c..d70467ddeebe 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java @@ -177,7 +177,7 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase { final float bouncerHideAmount = 0.05f; final float scaledFraction = - BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(bouncerHideAmount); + BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(bouncerHideAmount); bouncerExpansionCaptor.getValue().onExpansionChanged(bouncerHideAmount); verify(mBlurUtils).blurRadiusOfRatio(1 - scaledFraction); diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java index 4915dedb376e..3c28d48c2eb5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java @@ -16,10 +16,14 @@ package com.android.systemui.dreams; +import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN; +import static android.app.StatusBarManager.WINDOW_STATE_SHOWING; + import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -32,6 +36,7 @@ import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.provider.Settings; import android.testing.AndroidTestingRunner; +import android.view.View; import androidx.test.filters.SmallTest; @@ -40,6 +45,8 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController; import com.android.systemui.statusbar.policy.NextAlarmController; import com.android.systemui.statusbar.policy.ZenModeController; +import com.android.systemui.statusbar.window.StatusBarWindowStateController; +import com.android.systemui.statusbar.window.StatusBarWindowStateListener; import com.android.systemui.touch.TouchInsetManager; import com.android.systemui.util.time.DateFormatUtil; @@ -84,6 +91,8 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { ZenModeController mZenModeController; @Mock DreamOverlayNotificationCountProvider mDreamOverlayNotificationCountProvider; + @Mock + StatusBarWindowStateController mStatusBarWindowStateController; private final Executor mMainExecutor = Runnable::run; @@ -107,7 +116,8 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { mDateFormatUtil, mSensorPrivacyController, mDreamOverlayNotificationCountProvider, - mZenModeController); + mZenModeController, + mStatusBarWindowStateController); } @Test @@ -401,4 +411,41 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { verify(mView).showIcon( DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, false, null); } + + @Test + public void testStatusBarHiddenWhenSystemStatusBarShown() { + mController.onViewAttached(); + + final ArgumentCaptor<StatusBarWindowStateListener> + callbackCapture = ArgumentCaptor.forClass(StatusBarWindowStateListener.class); + verify(mStatusBarWindowStateController).addListener(callbackCapture.capture()); + callbackCapture.getValue().onStatusBarWindowStateChanged(WINDOW_STATE_SHOWING); + + verify(mView).setVisibility(View.INVISIBLE); + } + + @Test + public void testStatusBarShownWhenSystemStatusBarHidden() { + mController.onViewAttached(); + + final ArgumentCaptor<StatusBarWindowStateListener> + callbackCapture = ArgumentCaptor.forClass(StatusBarWindowStateListener.class); + verify(mStatusBarWindowStateController).addListener(callbackCapture.capture()); + callbackCapture.getValue().onStatusBarWindowStateChanged(WINDOW_STATE_HIDDEN); + + verify(mView).setVisibility(View.VISIBLE); + } + + @Test + public void testUnattachedStatusBarVisibilityUnchangedWhenSystemStatusBarHidden() { + mController.onViewAttached(); + mController.onViewDetached(); + + final ArgumentCaptor<StatusBarWindowStateListener> + callbackCapture = ArgumentCaptor.forClass(StatusBarWindowStateListener.class); + verify(mStatusBarWindowStateController).addListener(callbackCapture.capture()); + callbackCapture.getValue().onStatusBarWindowStateChanged(WINDOW_STATE_SHOWING); + + verify(mView, never()).setVisibility(anyInt()); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java index e175af7a037d..d0b3d6d2d2c7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java @@ -57,6 +57,8 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import java.util.Optional; + @SmallTest @RunWith(AndroidTestingRunner.class) public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { @@ -110,7 +112,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { mTouchHandler = new BouncerSwipeTouchHandler( mDisplayMetrics, mStatusBarKeyguardViewManager, - mCentralSurfaces, + Optional.of(mCentralSurfaces), mNotificationShadeWindowController, mValueAnimatorCreator, mVelocityTrackerFactory, diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferHelper.kt b/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferHelper.kt index 2cb19393d2c6..0720bdb06556 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferHelper.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferHelper.kt @@ -30,6 +30,7 @@ fun logcatLogBuffer(name: String = "EchoToLogcatLogBuffer") = * A [LogcatEchoTracker] that always allows echoing to the logcat. */ class LogcatEchoTrackerAlways : LogcatEchoTracker { + override val logInBackgroundThread = false override fun isBufferLoggable(bufferName: String, level: LogLevel): Boolean = true override fun isTagLoggable(tagName: String, level: LogLevel): Boolean = true } diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt index 6626bbe69706..b43856aae4cf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt @@ -24,7 +24,11 @@ import android.test.suitebuilder.annotation.SmallTest import com.android.internal.statusbar.IStatusBarService import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager +import com.android.systemui.statusbar.commandline.Command +import com.android.systemui.statusbar.commandline.CommandRegistry import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.argumentCaptor +import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.nullable import com.android.systemui.util.mockito.withArgCaptor @@ -37,10 +41,12 @@ import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock import org.mockito.Mockito.anyBoolean import org.mockito.Mockito.anyString +import org.mockito.Mockito.atLeastOnce import org.mockito.Mockito.inOrder import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions +import org.mockito.Mockito.verifyZeroInteractions import org.mockito.MockitoAnnotations import java.io.PrintWriter import java.io.Serializable @@ -56,16 +62,18 @@ import org.mockito.Mockito.`when` as whenever class FeatureFlagsDebugTest : SysuiTestCase() { private lateinit var mFeatureFlagsDebug: FeatureFlagsDebug - @Mock private lateinit var mFlagManager: FlagManager - @Mock private lateinit var mMockContext: Context - @Mock private lateinit var mSecureSettings: SecureSettings - @Mock private lateinit var mSystemProperties: SystemPropertiesHelper - @Mock private lateinit var mResources: Resources - @Mock private lateinit var mDumpManager: DumpManager - @Mock private lateinit var mBarService: IStatusBarService - private val mFlagMap = mutableMapOf<Int, Flag<*>>() - private lateinit var mBroadcastReceiver: BroadcastReceiver - private lateinit var mClearCacheAction: Consumer<Int> + @Mock private lateinit var flagManager: FlagManager + @Mock private lateinit var mockContext: Context + @Mock private lateinit var secureSettings: SecureSettings + @Mock private lateinit var systemProperties: SystemPropertiesHelper + @Mock private lateinit var resources: Resources + @Mock private lateinit var dumpManager: DumpManager + @Mock private lateinit var commandRegistry: CommandRegistry + @Mock private lateinit var barService: IStatusBarService + @Mock private lateinit var pw: PrintWriter + private val flagMap = mutableMapOf<Int, Flag<*>>() + private lateinit var broadcastReceiver: BroadcastReceiver + private lateinit var clearCacheAction: Consumer<Int> private val teamfoodableFlagA = BooleanFlag(500, false, true) private val teamfoodableFlagB = BooleanFlag(501, true, true) @@ -73,34 +81,35 @@ class FeatureFlagsDebugTest : SysuiTestCase() { @Before fun setup() { MockitoAnnotations.initMocks(this) - mFlagMap.put(teamfoodableFlagA.id, teamfoodableFlagA) - mFlagMap.put(teamfoodableFlagB.id, teamfoodableFlagB) + flagMap.put(teamfoodableFlagA.id, teamfoodableFlagA) + flagMap.put(teamfoodableFlagB.id, teamfoodableFlagB) mFeatureFlagsDebug = FeatureFlagsDebug( - mFlagManager, - mMockContext, - mSecureSettings, - mSystemProperties, - mResources, - mDumpManager, - mFlagMap, - mBarService + flagManager, + mockContext, + secureSettings, + systemProperties, + resources, + dumpManager, + flagMap, + commandRegistry, + barService ) - verify(mFlagManager).onSettingsChangedAction = any() - mBroadcastReceiver = withArgCaptor { - verify(mMockContext).registerReceiver(capture(), any(), nullable(), nullable(), + verify(flagManager).onSettingsChangedAction = any() + broadcastReceiver = withArgCaptor { + verify(mockContext).registerReceiver(capture(), any(), nullable(), nullable(), any()) } - mClearCacheAction = withArgCaptor { - verify(mFlagManager).clearCacheAction = capture() + clearCacheAction = withArgCaptor { + verify(flagManager).clearCacheAction = capture() } - whenever(mFlagManager.idToSettingsKey(any())).thenAnswer { "key-${it.arguments[0]}" } + whenever(flagManager.idToSettingsKey(any())).thenAnswer { "key-${it.arguments[0]}" } } @Test fun testReadBooleanFlag() { // Remember that the TEAMFOOD flag is id#1 and has special behavior. - whenever(mFlagManager.readFlagValue<Boolean>(eq(3), any())).thenReturn(true) - whenever(mFlagManager.readFlagValue<Boolean>(eq(4), any())).thenReturn(false) + whenever(flagManager.readFlagValue<Boolean>(eq(3), any())).thenReturn(true) + whenever(flagManager.readFlagValue<Boolean>(eq(4), any())).thenReturn(false) assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(2, true))).isTrue() assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(3, false))).isTrue() assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(4, true))).isFalse() @@ -109,7 +118,7 @@ class FeatureFlagsDebugTest : SysuiTestCase() { @Test fun testTeamFoodFlag_False() { - whenever(mFlagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(false) + whenever(flagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(false) assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagA)).isFalse() assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagB)).isTrue() @@ -120,7 +129,7 @@ class FeatureFlagsDebugTest : SysuiTestCase() { @Test fun testTeamFoodFlag_True() { - whenever(mFlagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(true) + whenever(flagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(true) assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagA)).isTrue() assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagB)).isTrue() @@ -131,11 +140,11 @@ class FeatureFlagsDebugTest : SysuiTestCase() { @Test fun testTeamFoodFlag_Overridden() { - whenever(mFlagManager.readFlagValue<Boolean>(eq(teamfoodableFlagA.id), any())) + whenever(flagManager.readFlagValue<Boolean>(eq(teamfoodableFlagA.id), any())) .thenReturn(true) - whenever(mFlagManager.readFlagValue<Boolean>(eq(teamfoodableFlagB.id), any())) + whenever(flagManager.readFlagValue<Boolean>(eq(teamfoodableFlagB.id), any())) .thenReturn(false) - whenever(mFlagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(true) + whenever(flagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(true) assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagA)).isTrue() assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagB)).isFalse() @@ -146,14 +155,14 @@ class FeatureFlagsDebugTest : SysuiTestCase() { @Test fun testReadResourceBooleanFlag() { - whenever(mResources.getBoolean(1001)).thenReturn(false) - whenever(mResources.getBoolean(1002)).thenReturn(true) - whenever(mResources.getBoolean(1003)).thenReturn(false) - whenever(mResources.getBoolean(1004)).thenAnswer { throw NameNotFoundException() } - whenever(mResources.getBoolean(1005)).thenAnswer { throw NameNotFoundException() } + whenever(resources.getBoolean(1001)).thenReturn(false) + whenever(resources.getBoolean(1002)).thenReturn(true) + whenever(resources.getBoolean(1003)).thenReturn(false) + whenever(resources.getBoolean(1004)).thenAnswer { throw NameNotFoundException() } + whenever(resources.getBoolean(1005)).thenAnswer { throw NameNotFoundException() } - whenever(mFlagManager.readFlagValue<Boolean>(eq(3), any())).thenReturn(true) - whenever(mFlagManager.readFlagValue<Boolean>(eq(5), any())).thenReturn(false) + whenever(flagManager.readFlagValue<Boolean>(eq(3), any())).thenReturn(true) + whenever(flagManager.readFlagValue<Boolean>(eq(5), any())).thenReturn(false) assertThat(mFeatureFlagsDebug.isEnabled(ResourceBooleanFlag(1, 1001))).isFalse() assertThat(mFeatureFlagsDebug.isEnabled(ResourceBooleanFlag(2, 1002))).isTrue() @@ -171,7 +180,7 @@ class FeatureFlagsDebugTest : SysuiTestCase() { @Test fun testReadSysPropBooleanFlag() { - whenever(mSystemProperties.getBoolean(anyString(), anyBoolean())).thenAnswer { + whenever(systemProperties.getBoolean(anyString(), anyBoolean())).thenAnswer { if ("b".equals(it.getArgument<String?>(0))) { return@thenAnswer true } @@ -187,8 +196,8 @@ class FeatureFlagsDebugTest : SysuiTestCase() { @Test fun testReadStringFlag() { - whenever(mFlagManager.readFlagValue<String>(eq(3), any())).thenReturn("foo") - whenever(mFlagManager.readFlagValue<String>(eq(4), any())).thenReturn("bar") + whenever(flagManager.readFlagValue<String>(eq(3), any())).thenReturn("foo") + whenever(flagManager.readFlagValue<String>(eq(4), any())).thenReturn("bar") assertThat(mFeatureFlagsDebug.getString(StringFlag(1, "biz"))).isEqualTo("biz") assertThat(mFeatureFlagsDebug.getString(StringFlag(2, "baz"))).isEqualTo("baz") assertThat(mFeatureFlagsDebug.getString(StringFlag(3, "buz"))).isEqualTo("foo") @@ -197,16 +206,16 @@ class FeatureFlagsDebugTest : SysuiTestCase() { @Test fun testReadResourceStringFlag() { - whenever(mResources.getString(1001)).thenReturn("") - whenever(mResources.getString(1002)).thenReturn("resource2") - whenever(mResources.getString(1003)).thenReturn("resource3") - whenever(mResources.getString(1004)).thenReturn(null) - whenever(mResources.getString(1005)).thenAnswer { throw NameNotFoundException() } - whenever(mResources.getString(1006)).thenAnswer { throw NameNotFoundException() } + whenever(resources.getString(1001)).thenReturn("") + whenever(resources.getString(1002)).thenReturn("resource2") + whenever(resources.getString(1003)).thenReturn("resource3") + whenever(resources.getString(1004)).thenReturn(null) + whenever(resources.getString(1005)).thenAnswer { throw NameNotFoundException() } + whenever(resources.getString(1006)).thenAnswer { throw NameNotFoundException() } - whenever(mFlagManager.readFlagValue<String>(eq(3), any())).thenReturn("override3") - whenever(mFlagManager.readFlagValue<String>(eq(4), any())).thenReturn("override4") - whenever(mFlagManager.readFlagValue<String>(eq(6), any())).thenReturn("override6") + whenever(flagManager.readFlagValue<String>(eq(3), any())).thenReturn("override3") + whenever(flagManager.readFlagValue<String>(eq(4), any())).thenReturn("override4") + whenever(flagManager.readFlagValue<String>(eq(6), any())).thenReturn("override6") assertThat(mFeatureFlagsDebug.getString(ResourceStringFlag(1, 1001))).isEqualTo("") assertThat(mFeatureFlagsDebug.getString(ResourceStringFlag(2, 1002))).isEqualTo("resource2") @@ -232,16 +241,16 @@ class FeatureFlagsDebugTest : SysuiTestCase() { addFlag(StringFlag(3, "flag3")) addFlag(ResourceStringFlag(4, 1004)) - mBroadcastReceiver.onReceive(mMockContext, null) - mBroadcastReceiver.onReceive(mMockContext, Intent()) - mBroadcastReceiver.onReceive(mMockContext, Intent("invalid action")) - mBroadcastReceiver.onReceive(mMockContext, Intent(FlagManager.ACTION_SET_FLAG)) + broadcastReceiver.onReceive(mockContext, null) + broadcastReceiver.onReceive(mockContext, Intent()) + broadcastReceiver.onReceive(mockContext, Intent("invalid action")) + broadcastReceiver.onReceive(mockContext, Intent(FlagManager.ACTION_SET_FLAG)) setByBroadcast(0, false) // unknown id does nothing setByBroadcast(1, "string") // wrong type does nothing setByBroadcast(2, 123) // wrong type does nothing setByBroadcast(3, false) // wrong type does nothing setByBroadcast(4, 123) // wrong type does nothing - verifyNoMoreInteractions(mFlagManager, mSecureSettings) + verifyNoMoreInteractions(flagManager, secureSettings) } @Test @@ -249,15 +258,15 @@ class FeatureFlagsDebugTest : SysuiTestCase() { addFlag(BooleanFlag(1, false)) // trying to erase an id not in the map does noting - mBroadcastReceiver.onReceive( - mMockContext, + broadcastReceiver.onReceive( + mockContext, Intent(FlagManager.ACTION_SET_FLAG).putExtra(FlagManager.EXTRA_ID, 0) ) - verifyNoMoreInteractions(mFlagManager, mSecureSettings) + verifyNoMoreInteractions(flagManager, secureSettings) // valid id with no value puts empty string in the setting - mBroadcastReceiver.onReceive( - mMockContext, + broadcastReceiver.onReceive( + mockContext, Intent(FlagManager.ACTION_SET_FLAG).putExtra(FlagManager.EXTRA_ID, 1) ) verifyPutData(1, "", numReads = 0) @@ -298,48 +307,102 @@ class FeatureFlagsDebugTest : SysuiTestCase() { @Test fun testSetFlagClearsCache() { val flag1 = addFlag(StringFlag(1, "flag1")) - whenever(mFlagManager.readFlagValue<String>(eq(1), any())).thenReturn("original") + whenever(flagManager.readFlagValue<String>(eq(1), any())).thenReturn("original") // gets the flag & cache it assertThat(mFeatureFlagsDebug.getString(flag1)).isEqualTo("original") - verify(mFlagManager).readFlagValue(eq(1), eq(StringFlagSerializer)) + verify(flagManager).readFlagValue(eq(1), eq(StringFlagSerializer)) // hit the cache assertThat(mFeatureFlagsDebug.getString(flag1)).isEqualTo("original") - verifyNoMoreInteractions(mFlagManager) + verifyNoMoreInteractions(flagManager) // set the flag setByBroadcast(1, "new") verifyPutData(1, "{\"type\":\"string\",\"value\":\"new\"}", numReads = 2) - whenever(mFlagManager.readFlagValue<String>(eq(1), any())).thenReturn("new") + whenever(flagManager.readFlagValue<String>(eq(1), any())).thenReturn("new") assertThat(mFeatureFlagsDebug.getString(flag1)).isEqualTo("new") - verify(mFlagManager, times(3)).readFlagValue(eq(1), eq(StringFlagSerializer)) + verify(flagManager, times(3)).readFlagValue(eq(1), eq(StringFlagSerializer)) + } + + @Test + fun testRegisterCommand() { + verify(commandRegistry).registerCommand(anyString(), any()) + } + + @Test + fun testNoOpCommand() { + val cmd = captureCommand() + + cmd.execute(pw, ArrayList()) + verify(pw, atLeastOnce()).println() + verify(flagManager).readFlagValue<Boolean>(eq(1), any()) + verifyZeroInteractions(secureSettings) + } + + @Test + fun testReadFlagCommand() { + addFlag(BooleanFlag(1, false)) + val cmd = captureCommand() + cmd.execute(pw, listOf("1")) + verify(flagManager).readFlagValue<Boolean>(eq(1), any()) + } + + @Test + fun testSetFlagCommand() { + addFlag(BooleanFlag(1, false)) + val cmd = captureCommand() + cmd.execute(pw, listOf("1", "on")) + verifyPutData(1, "{\"type\":\"boolean\",\"value\":true}") + } + + @Test + fun testToggleFlagCommand() { + addFlag(BooleanFlag(1, true)) + val cmd = captureCommand() + cmd.execute(pw, listOf("1", "toggle")) + verifyPutData(1, "{\"type\":\"boolean\",\"value\":false}", 2) + } + + @Test + fun testEraseFlagCommand() { + addFlag(BooleanFlag(1, true)) + val cmd = captureCommand() + cmd.execute(pw, listOf("1", "erase")) + verify(secureSettings).putStringForUser(eq("key-1"), eq(""), anyInt()) } private fun verifyPutData(id: Int, data: String, numReads: Int = 1) { - inOrder(mFlagManager, mSecureSettings).apply { - verify(mFlagManager, times(numReads)).readFlagValue(eq(id), any<FlagSerializer<*>>()) - verify(mFlagManager).idToSettingsKey(eq(id)) - verify(mSecureSettings).putStringForUser(eq("key-$id"), eq(data), anyInt()) - verify(mFlagManager).dispatchListenersAndMaybeRestart(eq(id), any()) + inOrder(flagManager, secureSettings).apply { + verify(flagManager, times(numReads)).readFlagValue(eq(id), any<FlagSerializer<*>>()) + verify(flagManager).idToSettingsKey(eq(id)) + verify(secureSettings).putStringForUser(eq("key-$id"), eq(data), anyInt()) + verify(flagManager).dispatchListenersAndMaybeRestart(eq(id), any()) }.verifyNoMoreInteractions() - verifyNoMoreInteractions(mFlagManager, mSecureSettings) + verifyNoMoreInteractions(flagManager, secureSettings) } private fun setByBroadcast(id: Int, value: Serializable?) { val intent = Intent(FlagManager.ACTION_SET_FLAG) intent.putExtra(FlagManager.EXTRA_ID, id) intent.putExtra(FlagManager.EXTRA_VALUE, value) - mBroadcastReceiver.onReceive(mMockContext, intent) + broadcastReceiver.onReceive(mockContext, intent) } private fun <F : Flag<*>> addFlag(flag: F): F { - val old = mFlagMap.put(flag.id, flag) + val old = flagMap.put(flag.id, flag) check(old == null) { "Flag ${flag.id} already registered" } return flag } + private fun captureCommand(): Command { + val captor = argumentCaptor<Function0<Command>>() + verify(commandRegistry).registerCommand(anyString(), capture(captor)) + + return captor.value.invoke() + } + @Test fun testDump() { val flag1 = BooleanFlag(1, true) @@ -350,10 +413,10 @@ class FeatureFlagsDebugTest : SysuiTestCase() { val flag6 = ResourceStringFlag(6, 1006) val flag7 = ResourceStringFlag(7, 1007) - whenever(mResources.getBoolean(1002)).thenReturn(true) - whenever(mResources.getString(1006)).thenReturn("resource1006") - whenever(mResources.getString(1007)).thenReturn("resource1007") - whenever(mFlagManager.readFlagValue(eq(7), eq(StringFlagSerializer))) + whenever(resources.getBoolean(1002)).thenReturn(true) + whenever(resources.getString(1006)).thenReturn("resource1006") + whenever(resources.getString(1007)).thenReturn("resource1007") + whenever(flagManager.readFlagValue(eq(7), eq(StringFlagSerializer))) .thenReturn("override7") // WHEN the flags have been accessed diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/AnimationBindHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/AnimationBindHandlerTest.kt new file mode 100644 index 000000000000..e4cab1810822 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/media/AnimationBindHandlerTest.kt @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media + +import org.mockito.Mockito.`when` as whenever +import android.graphics.drawable.Animatable2 +import android.graphics.drawable.Drawable +import android.test.suitebuilder.annotation.SmallTest +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import com.android.systemui.SysuiTestCase +import junit.framework.Assert.assertTrue +import junit.framework.Assert.assertFalse +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.Mockito.times +import org.mockito.Mockito.never +import org.mockito.junit.MockitoJUnit + +@SmallTest +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +class AnimationBindHandlerTest : SysuiTestCase() { + + private interface Callback : () -> Unit + private abstract class AnimatedDrawable : Drawable(), Animatable2 + private lateinit var handler: AnimationBindHandler + + @Mock private lateinit var animatable: AnimatedDrawable + @Mock private lateinit var animatable2: AnimatedDrawable + @Mock private lateinit var callback: Callback + + @JvmField @Rule val mockito = MockitoJUnit.rule() + + @Before + fun setUp() { + handler = AnimationBindHandler() + } + + @After + fun tearDown() {} + + @Test + fun registerNoAnimations_executeCallbackImmediately() { + handler.tryExecute(callback) + verify(callback).invoke() + } + + @Test + fun registerStoppedAnimations_executeCallbackImmediately() { + whenever(animatable.isRunning).thenReturn(false) + whenever(animatable2.isRunning).thenReturn(false) + + handler.tryExecute(callback) + verify(callback).invoke() + } + + @Test + fun registerRunningAnimations_executeCallbackDelayed() { + whenever(animatable.isRunning).thenReturn(true) + whenever(animatable2.isRunning).thenReturn(true) + + handler.tryRegister(animatable) + handler.tryRegister(animatable2) + handler.tryExecute(callback) + + verify(callback, never()).invoke() + + whenever(animatable.isRunning).thenReturn(false) + handler.onAnimationEnd(animatable) + verify(callback, never()).invoke() + + whenever(animatable2.isRunning).thenReturn(false) + handler.onAnimationEnd(animatable2) + verify(callback, times(1)).invoke() + } + + @Test + fun repeatedEndCallback_executeSingleCallback() { + whenever(animatable.isRunning).thenReturn(true) + + handler.tryRegister(animatable) + handler.tryExecute(callback) + + verify(callback, never()).invoke() + + whenever(animatable.isRunning).thenReturn(false) + handler.onAnimationEnd(animatable) + handler.onAnimationEnd(animatable) + handler.onAnimationEnd(animatable) + verify(callback, times(1)).invoke() + } + + @Test + fun registerUnregister_executeImmediately() { + whenever(animatable.isRunning).thenReturn(true) + + handler.tryRegister(animatable) + handler.unregisterAll() + handler.tryExecute(callback) + + verify(callback).invoke() + } + + @Test + fun updateRebindId_returnsAsExpected() { + // Previous or current call is null, returns true + assertTrue(handler.updateRebindId(null)) + assertTrue(handler.updateRebindId(null)) + assertTrue(handler.updateRebindId(null)) + assertTrue(handler.updateRebindId(10)) + assertTrue(handler.updateRebindId(null)) + assertTrue(handler.updateRebindId(20)) + + // Different integer from prevoius, returns true + assertTrue(handler.updateRebindId(10)) + assertTrue(handler.updateRebindId(20)) + + // Matches previous call, returns false + assertFalse(handler.updateRebindId(20)) + assertFalse(handler.updateRebindId(20)) + assertTrue(handler.updateRebindId(10)) + assertFalse(handler.updateRebindId(10)) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/ColorSchemeTransitionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/ColorSchemeTransitionTest.kt new file mode 100644 index 000000000000..8f967ab5294f --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/media/ColorSchemeTransitionTest.kt @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media + +import org.mockito.Mockito.`when` as whenever +import android.animation.ValueAnimator +import android.graphics.Color +import android.test.suitebuilder.annotation.SmallTest +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import com.android.systemui.SysuiTestCase +import com.android.systemui.monet.ColorScheme +import junit.framework.Assert.assertEquals +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.never +import org.mockito.Mockito.times +import org.mockito.Mockito.verify +import org.mockito.junit.MockitoJUnit + +private const val DEFAULT_COLOR = Color.RED +private const val TARGET_COLOR = Color.BLUE + +@SmallTest +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +class ColorSchemeTransitionTest : SysuiTestCase() { + + private interface ExtractCB : (ColorScheme) -> Int + private interface ApplyCB : (Int) -> Unit + private lateinit var colorTransition: ColorTransition + private lateinit var colorSchemeTransition: ColorSchemeTransition + + @Mock private lateinit var mockTransition: ColorTransition + @Mock private lateinit var valueAnimator: ValueAnimator + @Mock private lateinit var colorScheme: ColorScheme + @Mock private lateinit var extractColor: ExtractCB + @Mock private lateinit var applyColor: ApplyCB + + private lateinit var transitionFactory: ColorTransitionFactory + @Mock private lateinit var mediaViewHolder: MediaViewHolder + + @JvmField @Rule val mockitoRule = MockitoJUnit.rule() + + @Before + fun setUp() { + transitionFactory = { default, extractColor, applyColor -> mockTransition } + whenever(extractColor.invoke(colorScheme)).thenReturn(TARGET_COLOR) + + colorSchemeTransition = ColorSchemeTransition(context, mediaViewHolder, transitionFactory) + + colorTransition = object : ColorTransition(DEFAULT_COLOR, extractColor, applyColor) { + override fun buildAnimator(): ValueAnimator { + return valueAnimator + } + } + } + + @After + fun tearDown() {} + + @Test + fun testColorTransition_nullColorScheme_keepsDefault() { + colorTransition.updateColorScheme(null) + verify(applyColor, times(1)).invoke(DEFAULT_COLOR) + verify(valueAnimator, never()).start() + assertEquals(DEFAULT_COLOR, colorTransition.sourceColor) + assertEquals(DEFAULT_COLOR, colorTransition.targetColor) + } + + @Test + fun testColorTransition_newColor_startsAnimation() { + colorTransition.updateColorScheme(colorScheme) + verify(applyColor, times(1)).invoke(DEFAULT_COLOR) + verify(valueAnimator, times(1)).start() + assertEquals(DEFAULT_COLOR, colorTransition.sourceColor) + assertEquals(TARGET_COLOR, colorTransition.targetColor) + } + + @Test + fun testColorTransition_sameColor_noAnimation() { + whenever(extractColor.invoke(colorScheme)).thenReturn(DEFAULT_COLOR) + colorTransition.updateColorScheme(colorScheme) + verify(valueAnimator, never()).start() + assertEquals(DEFAULT_COLOR, colorTransition.sourceColor) + assertEquals(DEFAULT_COLOR, colorTransition.targetColor) + } + + @Test + fun testColorTransition_colorAnimation_startValues() { + val expectedColor = DEFAULT_COLOR + whenever(valueAnimator.animatedFraction).thenReturn(0f) + colorTransition.updateColorScheme(colorScheme) + colorTransition.onAnimationUpdate(valueAnimator) + + assertEquals(expectedColor, colorTransition.currentColor) + assertEquals(expectedColor, colorTransition.sourceColor) + verify(applyColor, times(2)).invoke(expectedColor) // applied once in constructor + } + + @Test + fun testColorTransition_colorAnimation_endValues() { + val expectedColor = TARGET_COLOR + whenever(valueAnimator.animatedFraction).thenReturn(1f) + colorTransition.updateColorScheme(colorScheme) + colorTransition.onAnimationUpdate(valueAnimator) + + assertEquals(expectedColor, colorTransition.currentColor) + assertEquals(expectedColor, colorTransition.targetColor) + verify(applyColor).invoke(expectedColor) + } + + @Test + fun testColorTransition_colorAnimation_interpolatedMidpoint() { + val expectedColor = Color.rgb(186, 0, 186) + whenever(valueAnimator.animatedFraction).thenReturn(0.5f) + colorTransition.updateColorScheme(colorScheme) + colorTransition.onAnimationUpdate(valueAnimator) + + assertEquals(expectedColor, colorTransition.currentColor) + verify(applyColor).invoke(expectedColor) + } + + @Test + fun testColorSchemeTransition_update() { + colorSchemeTransition.updateColorScheme(colorScheme) + verify(mockTransition, times(6)).updateColorScheme(colorScheme) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt index 67fe0445e225..1522ee8cd6d5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt @@ -19,6 +19,7 @@ package com.android.systemui.media import android.testing.AndroidTestingRunner import android.testing.TestableLooper import androidx.test.filters.SmallTest +import com.android.internal.logging.InstanceId import com.android.systemui.SysuiTestCase import com.android.systemui.classifier.FalsingCollector import com.android.systemui.dagger.qualifiers.Main @@ -28,6 +29,7 @@ import com.android.systemui.plugins.FalsingManager import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.concurrency.DelayableExecutor +import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.FakeSystemClock import junit.framework.Assert.assertEquals import junit.framework.Assert.assertTrue @@ -225,4 +227,19 @@ class MediaCarouselControllerTest : SysuiTestCase() { animate = false) verify(logger).logCarouselPosition(MediaHierarchyManager.LOCATION_DREAM_OVERLAY) } + + @Test + fun testRecommendationRemoved_logged() { + val packageName = "smartspace package" + val instanceId = InstanceId.fakeInstanceId(123) + + val smartspaceData = EMPTY_SMARTSPACE_MEDIA_DATA.copy( + packageName = packageName, + instanceId = instanceId + ) + MediaPlayerData.addMediaRecommendation(SMARTSPACE_KEY, smartspaceData, panel, true, clock) + mediaCarouselController.removePlayer(SMARTSPACE_KEY) + + verify(logger).logRecommendationRemoved(eq(packageName), eq(instanceId!!)) + } }
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt index 14db4bf81e14..33db99342586 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt @@ -16,23 +16,32 @@ package com.android.systemui.media +import android.animation.Animator +import android.animation.AnimatorSet import android.app.PendingIntent +import android.app.smartspace.SmartspaceAction +import android.content.Context import org.mockito.Mockito.`when` as whenever import android.content.Intent +import android.content.pm.ApplicationInfo +import android.content.pm.PackageManager import android.graphics.Color import android.graphics.drawable.Animatable2 import android.graphics.drawable.AnimatedVectorDrawable import android.graphics.drawable.GradientDrawable +import android.graphics.drawable.Icon import android.graphics.drawable.RippleDrawable import android.media.MediaMetadata import android.media.session.MediaSession import android.media.session.PlaybackState +import android.os.Bundle import android.os.Handler import android.provider.Settings.ACTION_MEDIA_CONTROLS_SETTINGS import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.View import android.view.ViewGroup +import android.view.animation.Interpolator import android.widget.FrameLayout import android.widget.ImageButton import android.widget.ImageView @@ -43,16 +52,22 @@ import androidx.constraintlayout.widget.ConstraintSet import androidx.lifecycle.LiveData import androidx.test.filters.SmallTest import com.android.internal.logging.InstanceId +import com.android.systemui.ActivityIntentHelper import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.media.dialog.MediaOutputDialogFactory import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.FalsingManager +import com.android.systemui.statusbar.NotificationLockscreenUserManager +import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.animation.TransitionLayout import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.KotlinArgumentCaptor +import com.android.systemui.util.mockito.argumentCaptor +import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq +import com.android.systemui.util.mockito.nullable import com.android.systemui.util.mockito.withArgCaptor import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat @@ -66,7 +81,7 @@ import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.anyLong import org.mockito.Mock -import org.mockito.Mockito.any +import org.mockito.Mockito.anyString import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.reset @@ -75,7 +90,6 @@ import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit private const val KEY = "TEST_KEY" -private const val BG_COLOR = Color.RED private const val PACKAGE = "PKG" private const val ARTIST = "ARTIST" private const val TITLE = "TITLE" @@ -107,6 +121,7 @@ public class MediaControlPanelTest : SysuiTestCase() { @Mock private lateinit var collapsedSet: ConstraintSet @Mock private lateinit var mediaOutputDialogFactory: MediaOutputDialogFactory @Mock private lateinit var mediaCarouselController: MediaCarouselController + @Mock private lateinit var mediaCarouselScrollHandler: MediaCarouselScrollHandler @Mock private lateinit var falsingManager: FalsingManager @Mock private lateinit var transitionParent: ViewGroup private lateinit var appIcon: ImageView @@ -132,6 +147,7 @@ public class MediaControlPanelTest : SysuiTestCase() { private lateinit var actionsTopBarrier: Barrier @Mock private lateinit var longPressText: TextView @Mock private lateinit var handler: Handler + @Mock private lateinit var mockAnimator: AnimatorSet private lateinit var settings: ImageButton private lateinit var cancel: View private lateinit var cancelText: TextView @@ -145,6 +161,27 @@ public class MediaControlPanelTest : SysuiTestCase() { private val clock = FakeSystemClock() @Mock private lateinit var logger: MediaUiEventLogger @Mock private lateinit var instanceId: InstanceId + @Mock private lateinit var packageManager: PackageManager + @Mock private lateinit var applicationInfo: ApplicationInfo + @Mock private lateinit var keyguardStateController: KeyguardStateController + @Mock private lateinit var activityIntentHelper: ActivityIntentHelper + @Mock private lateinit var lockscreenUserManager: NotificationLockscreenUserManager + + @Mock private lateinit var recommendationViewHolder: RecommendationViewHolder + @Mock private lateinit var smartspaceAction: SmartspaceAction + private lateinit var smartspaceData: SmartspaceMediaData + @Mock private lateinit var coverContainer1: ViewGroup + @Mock private lateinit var coverContainer2: ViewGroup + @Mock private lateinit var coverContainer3: ViewGroup + private lateinit var coverItem1: ImageView + private lateinit var coverItem2: ImageView + private lateinit var coverItem3: ImageView + private lateinit var recTitle1: TextView + private lateinit var recTitle2: TextView + private lateinit var recTitle3: TextView + private lateinit var recSubtitle1: TextView + private lateinit var recSubtitle2: TextView + private lateinit var recSubtitle3: TextView @JvmField @Rule val mockito = MockitoJUnit.rule() @@ -155,7 +192,17 @@ public class MediaControlPanelTest : SysuiTestCase() { whenever(mediaViewController.expandedLayout).thenReturn(expandedSet) whenever(mediaViewController.collapsedLayout).thenReturn(collapsedSet) - player = MediaControlPanel( + // Set up package manager mocks + val icon = context.getDrawable(R.drawable.ic_android) + whenever(packageManager.getApplicationIcon(anyString())).thenReturn(icon) + whenever(packageManager.getApplicationIcon(any(ApplicationInfo::class.java))) + .thenReturn(icon) + whenever(packageManager.getApplicationInfo(eq(PACKAGE), anyInt())) + .thenReturn(applicationInfo) + whenever(packageManager.getApplicationLabel(any())).thenReturn(PACKAGE) + context.setMockPackageManager(packageManager) + + player = object : MediaControlPanel( context, bgExecutor, mainExecutor, @@ -168,9 +215,71 @@ public class MediaControlPanelTest : SysuiTestCase() { mediaCarouselController, falsingManager, clock, - logger + logger, + keyguardStateController, + activityIntentHelper, + lockscreenUserManager) { + override fun loadAnimator( + animId: Int, + otionInterpolator: Interpolator, + vararg targets: View + ): AnimatorSet { + return mockAnimator + } + } + + initMediaViewHolderMocks() + + // Create media session + val metadataBuilder = MediaMetadata.Builder().apply { + putString(MediaMetadata.METADATA_KEY_ARTIST, SESSION_ARTIST) + putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_TITLE) + } + val playbackBuilder = PlaybackState.Builder().apply { + setState(PlaybackState.STATE_PAUSED, 6000L, 1f) + setActions(PlaybackState.ACTION_PLAY) + } + session = MediaSession(context, SESSION_KEY).apply { + setMetadata(metadataBuilder.build()) + setPlaybackState(playbackBuilder.build()) + } + session.setActive(true) + + mediaData = MediaTestUtils.emptyMediaData.copy( + artist = ARTIST, + song = TITLE, + packageName = PACKAGE, + token = session.sessionToken, + device = device, + instanceId = instanceId) + + // Set up recommendation view + initRecommendationViewHolderMocks() + + // Set valid recommendation data + val extras = Bundle() + val intent = Intent().apply { + putExtras(extras) + setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + whenever(smartspaceAction.intent).thenReturn(intent) + whenever(smartspaceAction.extras).thenReturn(extras) + smartspaceData = EMPTY_SMARTSPACE_MEDIA_DATA.copy( + packageName = PACKAGE, + instanceId = instanceId, + recommendations = listOf(smartspaceAction), + cardAction = smartspaceAction ) + } + + /** + * Initialize elements in media view holder + */ + private fun initMediaViewHolderMocks() { whenever(seekBarViewModel.progress).thenReturn(seekBarData) + whenever(mediaCarouselController.mediaCarouselScrollHandler) + .thenReturn(mediaCarouselScrollHandler) + whenever(mediaCarouselScrollHandler.qsExpanded).thenReturn(false) // Set up mock views for the players appIcon = ImageView(context) @@ -218,37 +327,6 @@ public class MediaControlPanelTest : SysuiTestCase() { action4.id) } - initMediaViewHolderMocks() - - // Create media session - val metadataBuilder = MediaMetadata.Builder().apply { - putString(MediaMetadata.METADATA_KEY_ARTIST, SESSION_ARTIST) - putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_TITLE) - } - val playbackBuilder = PlaybackState.Builder().apply { - setState(PlaybackState.STATE_PAUSED, 6000L, 1f) - setActions(PlaybackState.ACTION_PLAY) - } - session = MediaSession(context, SESSION_KEY).apply { - setMetadata(metadataBuilder.build()) - setPlaybackState(playbackBuilder.build()) - } - session.setActive(true) - - mediaData = MediaTestUtils.emptyMediaData.copy( - backgroundColor = BG_COLOR, - artist = ARTIST, - song = TITLE, - packageName = PACKAGE, - token = session.sessionToken, - device = device, - instanceId = instanceId) - } - - /** - * Initialize elements in media view holder - */ - private fun initMediaViewHolderMocks() { whenever(viewHolder.player).thenReturn(view) whenever(viewHolder.appIcon).thenReturn(appIcon) whenever(viewHolder.albumView).thenReturn(albumView) @@ -297,6 +375,52 @@ public class MediaControlPanelTest : SysuiTestCase() { whenever(viewHolder.actionsTopBarrier).thenReturn(actionsTopBarrier) } + /** + * Initialize elements for the recommendation view holder + */ + private fun initRecommendationViewHolderMocks() { + recTitle1 = TextView(context) + recTitle2 = TextView(context) + recTitle3 = TextView(context) + recSubtitle1 = TextView(context) + recSubtitle2 = TextView(context) + recSubtitle3 = TextView(context) + + whenever(recommendationViewHolder.recommendations).thenReturn(view) + whenever(recommendationViewHolder.cardIcon).thenReturn(appIcon) + + // Add a recommendation item + coverItem1 = ImageView(context).also { it.setId(R.id.media_cover1) } + coverItem2 = ImageView(context).also { it.setId(R.id.media_cover2) } + coverItem3 = ImageView(context).also { it.setId(R.id.media_cover3) } + + whenever(recommendationViewHolder.mediaCoverItems) + .thenReturn(listOf(coverItem1, coverItem2, coverItem3)) + whenever(recommendationViewHolder.mediaCoverContainers) + .thenReturn(listOf(coverContainer1, coverContainer2, coverContainer3)) + whenever(recommendationViewHolder.mediaTitles) + .thenReturn(listOf(recTitle1, recTitle2, recTitle3)) + whenever(recommendationViewHolder.mediaSubtitles).thenReturn( + listOf(recSubtitle1, recSubtitle2, recSubtitle3) + ) + + // Long press menu + whenever(recommendationViewHolder.settings).thenReturn(settings) + whenever(recommendationViewHolder.cancel).thenReturn(cancel) + whenever(recommendationViewHolder.dismiss).thenReturn(dismiss) + + val actionIcon = Icon.createWithResource(context, R.drawable.ic_android) + whenever(smartspaceAction.icon).thenReturn(actionIcon) + + // Needed for card and item action click + val mockContext = mock(Context::class.java) + whenever(view.context).thenReturn(mockContext) + whenever(coverContainer1.context).thenReturn(mockContext) + whenever(coverContainer2.context).thenReturn(mockContext) + whenever(coverContainer3.context).thenReturn(mockContext) + + } + @After fun tearDown() { session.release() @@ -357,6 +481,64 @@ public class MediaControlPanelTest : SysuiTestCase() { } @Test + fun bindSemanticActions_reservedPrev() { + val icon = context.getDrawable(android.R.drawable.ic_media_play) + val bg = context.getDrawable(R.drawable.qs_media_round_button_background) + + // Setup button state: no prev or next button and their slots reserved + val semanticActions = MediaButton( + playOrPause = MediaAction(icon, Runnable {}, "play", bg), + nextOrCustom = null, + prevOrCustom = null, + custom0 = MediaAction(icon, null, "custom 0", bg), + custom1 = MediaAction(icon, null, "custom 1", bg), + false, + true + ) + val state = mediaData.copy(semanticActions = semanticActions) + + player.attachPlayer(viewHolder) + player.bindPlayer(state, PACKAGE) + + assertThat(actionPrev.isEnabled()).isFalse() + assertThat(actionPrev.drawable).isNull() + verify(expandedSet).setVisibility(R.id.actionPrev, ConstraintSet.INVISIBLE) + + assertThat(actionNext.isEnabled()).isFalse() + assertThat(actionNext.drawable).isNull() + verify(expandedSet).setVisibility(R.id.actionNext, ConstraintSet.GONE) + } + + @Test + fun bindSemanticActions_reservedNext() { + val icon = context.getDrawable(android.R.drawable.ic_media_play) + val bg = context.getDrawable(R.drawable.qs_media_round_button_background) + + // Setup button state: no prev or next button and their slots reserved + val semanticActions = MediaButton( + playOrPause = MediaAction(icon, Runnable {}, "play", bg), + nextOrCustom = null, + prevOrCustom = null, + custom0 = MediaAction(icon, null, "custom 0", bg), + custom1 = MediaAction(icon, null, "custom 1", bg), + true, + false + ) + val state = mediaData.copy(semanticActions = semanticActions) + + player.attachPlayer(viewHolder) + player.bindPlayer(state, PACKAGE) + + assertThat(actionPrev.isEnabled()).isFalse() + assertThat(actionPrev.drawable).isNull() + verify(expandedSet).setVisibility(R.id.actionPrev, ConstraintSet.GONE) + + assertThat(actionNext.isEnabled()).isFalse() + assertThat(actionNext.drawable).isNull() + verify(expandedSet).setVisibility(R.id.actionNext, ConstraintSet.INVISIBLE) + } + + @Test fun bind_seekBarDisabled_seekBarVisibilityIsSetToInvisible() { whenever(seekBarViewModel.getEnabled()).thenReturn(false) @@ -390,7 +572,7 @@ public class MediaControlPanelTest : SysuiTestCase() { val icon = context.getDrawable(android.R.drawable.ic_media_play) val semanticActions = MediaButton( prevOrCustom = MediaAction(icon, {}, "prev", null), - nextOrCustom = MediaAction(icon, {}, "next", null), + nextOrCustom = MediaAction(icon, {}, "next", null) ) val state = mediaData.copy(semanticActions = semanticActions) @@ -424,7 +606,7 @@ public class MediaControlPanelTest : SysuiTestCase() { val icon = context.getDrawable(android.R.drawable.ic_media_play) val semanticActions = MediaButton( prevOrCustom = null, - nextOrCustom = MediaAction(icon, {}, "next", null), + nextOrCustom = MediaAction(icon, {}, "next", null) ) val state = mediaData.copy(semanticActions = semanticActions) player.attachPlayer(viewHolder) @@ -444,7 +626,7 @@ public class MediaControlPanelTest : SysuiTestCase() { val icon = context.getDrawable(android.R.drawable.ic_media_play) val semanticActions = MediaButton( prevOrCustom = MediaAction(icon, {}, "prev", null), - nextOrCustom = null, + nextOrCustom = null ) val state = mediaData.copy(semanticActions = semanticActions) player.attachPlayer(viewHolder) @@ -464,7 +646,7 @@ public class MediaControlPanelTest : SysuiTestCase() { val icon = context.getDrawable(android.R.drawable.ic_media_play) val semanticActions = MediaButton( prevOrCustom = MediaAction(icon, {}, "prev", null), - nextOrCustom = MediaAction(icon, {}, "next", null), + nextOrCustom = MediaAction(icon, {}, "next", null) ) val state = mediaData.copy(semanticActions = semanticActions) player.attachPlayer(viewHolder) @@ -486,7 +668,7 @@ public class MediaControlPanelTest : SysuiTestCase() { val icon = context.getDrawable(android.R.drawable.ic_media_play) val semanticActions = MediaButton( prevOrCustom = MediaAction(icon, {}, "prev", null), - nextOrCustom = MediaAction(icon, {}, "next", null), + nextOrCustom = MediaAction(icon, {}, "next", null) ) val state = mediaData.copy(semanticActions = semanticActions) @@ -518,9 +700,11 @@ public class MediaControlPanelTest : SysuiTestCase() { MediaAction(icon, null, "custom 0", bg), MediaAction(icon, Runnable {}, "custom 1", bg) ) - val state = mediaData.copy(actions = actions, + val state = mediaData.copy( + actions = actions, actionsToShowInCompact = listOf(1, 2), - semanticActions = null) + semanticActions = null + ) player.attachPlayer(viewHolder) player.bindPlayer(state, PACKAGE) @@ -569,11 +753,14 @@ public class MediaControlPanelTest : SysuiTestCase() { val icon = context.getDrawable(R.drawable.ic_media_play) val bg = context.getDrawable(R.drawable.ic_media_play_container) val semanticActions0 = MediaButton( - playOrPause = MediaAction(mockAvd0, Runnable {}, "play", null)) + playOrPause = MediaAction(mockAvd0, Runnable {}, "play", null) + ) val semanticActions1 = MediaButton( - playOrPause = MediaAction(mockAvd1, Runnable {}, "pause", null)) + playOrPause = MediaAction(mockAvd1, Runnable {}, "pause", null) + ) val semanticActions2 = MediaButton( - playOrPause = MediaAction(mockAvd2, Runnable {}, "loading", null)) + playOrPause = MediaAction(mockAvd2, Runnable {}, "loading", null) + ) val state0 = mediaData.copy(semanticActions = semanticActions0) val state1 = mediaData.copy(semanticActions = semanticActions1) val state2 = mediaData.copy(semanticActions = semanticActions2) @@ -613,8 +800,8 @@ public class MediaControlPanelTest : SysuiTestCase() { assertThat(actionPlayPause.getBackground()).isNull() verify(mockAvd0, times(1)) .registerAnimationCallback(any(Animatable2.AnimationCallback::class.java)) - verify(mockAvd1, times(1) - ).registerAnimationCallback(any(Animatable2.AnimationCallback::class.java)) + verify(mockAvd1, times(1)) + .registerAnimationCallback(any(Animatable2.AnimationCallback::class.java)) verify(mockAvd2, times(1)) .registerAnimationCallback(any(Animatable2.AnimationCallback::class.java)) verify(mockAvd0, times(1)) @@ -629,8 +816,53 @@ public class MediaControlPanelTest : SysuiTestCase() { fun bindText() { player.attachPlayer(viewHolder) player.bindPlayer(mediaData, PACKAGE) + + // Capture animation handler + val captor = argumentCaptor<Animator.AnimatorListener>() + verify(mockAnimator, times(2)).addListener(captor.capture()) + val handler = captor.value + + // Validate text views unchanged but animation started + assertThat(titleText.getText()).isEqualTo("") + assertThat(artistText.getText()).isEqualTo("") + verify(mockAnimator, times(1)).start() + + // Binding only after animator runs + handler.onAnimationEnd(mockAnimator) assertThat(titleText.getText()).isEqualTo(TITLE) assertThat(artistText.getText()).isEqualTo(ARTIST) + + // Rebinding should not trigger animation + player.bindPlayer(mediaData, PACKAGE) + verify(mockAnimator, times(1)).start() + } + + @Test + fun bindTextInterrupted() { + val data0 = mediaData.copy(artist = "ARTIST_0") + val data1 = mediaData.copy(artist = "ARTIST_1") + val data2 = mediaData.copy(artist = "ARTIST_2") + + player.attachPlayer(viewHolder) + player.bindPlayer(data0, PACKAGE) + + // Capture animation handler + val captor = argumentCaptor<Animator.AnimatorListener>() + verify(mockAnimator, times(2)).addListener(captor.capture()) + val handler = captor.value + + handler.onAnimationEnd(mockAnimator) + assertThat(artistText.getText()).isEqualTo("ARTIST_0") + + // Bind trigges new animation + player.bindPlayer(data1, PACKAGE) + verify(mockAnimator, times(2)).start() + whenever(mockAnimator.isRunning()).thenReturn(true) + + // Rebind before animation end binds corrct data + player.bindPlayer(data2, PACKAGE) + handler.onAnimationEnd(mockAnimator) + assertThat(artistText.getText()).isEqualTo("ARTIST_2") } @Test @@ -923,6 +1155,166 @@ public class MediaControlPanelTest : SysuiTestCase() { verify(logger).logSeek(anyInt(), eq(PACKAGE), eq(instanceId)) } + @Test + fun tapContentView_showOverLockscreen_openActivity() { + // WHEN we are on lockscreen and this activity can show over lockscreen + whenever(keyguardStateController.isShowing).thenReturn(true) + whenever(activityIntentHelper.wouldShowOverLockscreen(any(), any())).thenReturn(true) + + val clickIntent = mock(Intent::class.java) + val pendingIntent = mock(PendingIntent::class.java) + whenever(pendingIntent.intent).thenReturn(clickIntent) + val captor = ArgumentCaptor.forClass(View.OnClickListener::class.java) + val data = mediaData.copy(clickIntent = pendingIntent) + player.attachPlayer(viewHolder) + player.bindPlayer(data, KEY) + verify(viewHolder.player).setOnClickListener(captor.capture()) + + // THEN it shows without dismissing keyguard first + captor.value.onClick(viewHolder.player) + verify(activityStarter).startActivity(eq(clickIntent), eq(true), + nullable(), eq(true)) + } + + @Test + fun tapContentView_noShowOverLockscreen_dismissKeyguard() { + // WHEN we are on lockscreen and the activity cannot show over lockscreen + whenever(keyguardStateController.isShowing).thenReturn(true) + whenever(activityIntentHelper.wouldShowOverLockscreen(any(), any())).thenReturn(false) + + val clickIntent = mock(Intent::class.java) + val pendingIntent = mock(PendingIntent::class.java) + whenever(pendingIntent.intent).thenReturn(clickIntent) + val captor = ArgumentCaptor.forClass(View.OnClickListener::class.java) + val data = mediaData.copy(clickIntent = pendingIntent) + player.attachPlayer(viewHolder) + player.bindPlayer(data, KEY) + verify(viewHolder.player).setOnClickListener(captor.capture()) + + // THEN keyguard has to be dismissed + captor.value.onClick(viewHolder.player) + verify(activityStarter).postStartActivityDismissingKeyguard(eq(pendingIntent), any()) + } + + @Test + fun recommendation_gutsClosed_longPressOpens() { + player.attachRecommendation(recommendationViewHolder) + player.bindRecommendation(smartspaceData) + whenever(mediaViewController.isGutsVisible).thenReturn(false) + + val captor = ArgumentCaptor.forClass(View.OnLongClickListener::class.java) + verify(recommendationViewHolder.recommendations).setOnLongClickListener(captor.capture()) + + captor.value.onLongClick(recommendationViewHolder.recommendations) + verify(mediaViewController).openGuts() + verify(logger).logLongPressOpen(anyInt(), eq(PACKAGE), eq(instanceId)) + } + + @Test + fun recommendation_settingsButtonClick_isLogged() { + player.attachRecommendation(recommendationViewHolder) + player.bindRecommendation(smartspaceData) + + settings.callOnClick() + verify(logger).logLongPressSettings(anyInt(), eq(PACKAGE), eq(instanceId)) + + val captor = ArgumentCaptor.forClass(Intent::class.java) + verify(activityStarter).startActivity(captor.capture(), eq(true)) + + assertThat(captor.value.action).isEqualTo(ACTION_MEDIA_CONTROLS_SETTINGS) + } + + @Test + fun recommendation_dismissButton_isLogged() { + player.attachRecommendation(recommendationViewHolder) + player.bindRecommendation(smartspaceData) + + dismiss.callOnClick() + verify(logger).logLongPressDismiss(anyInt(), eq(PACKAGE), eq(instanceId)) + } + + @Test + fun recommendation_tapOnCard_isLogged() { + val captor = ArgumentCaptor.forClass(View.OnClickListener::class.java) + player.attachRecommendation(recommendationViewHolder) + player.bindRecommendation(smartspaceData) + + verify(recommendationViewHolder.recommendations).setOnClickListener(captor.capture()) + captor.value.onClick(recommendationViewHolder.recommendations) + + verify(logger).logRecommendationCardTap(eq(PACKAGE), eq(instanceId)) + } + + @Test + fun recommendation_tapOnItem_isLogged() { + val captor = ArgumentCaptor.forClass(View.OnClickListener::class.java) + player.attachRecommendation(recommendationViewHolder) + player.bindRecommendation(smartspaceData) + + verify(coverContainer1).setOnClickListener(captor.capture()) + captor.value.onClick(recommendationViewHolder.recommendations) + + verify(logger).logRecommendationItemTap(eq(PACKAGE), eq(instanceId), eq(0)) + } + + @Test + fun bindRecommendation_hasTitlesAndSubtitles() { + player.attachRecommendation(recommendationViewHolder) + + val title1 = "Title1" + val title2 = "Title2" + val title3 = "Title3" + val subtitle1 = "Subtitle1" + val subtitle2 = "Subtitle2" + val subtitle3 = "Subtitle3" + + val data = smartspaceData.copy( + recommendations = listOf( + SmartspaceAction.Builder("id1", title1) + .setSubtitle(subtitle1) + .setIcon(Icon.createWithResource(context, R.drawable.ic_1x_mobiledata)) + .setExtras(Bundle.EMPTY) + .build(), + SmartspaceAction.Builder("id2", title2) + .setSubtitle(subtitle2) + .setIcon(Icon.createWithResource(context, R.drawable.ic_alarm)) + .setExtras(Bundle.EMPTY) + .build(), + SmartspaceAction.Builder("id3", title3) + .setSubtitle(subtitle3) + .setIcon(Icon.createWithResource(context, R.drawable.ic_3g_mobiledata)) + .setExtras(Bundle.EMPTY) + .build() + ) + ) + player.bindRecommendation(data) + + assertThat(recTitle1.text).isEqualTo(title1) + assertThat(recTitle2.text).isEqualTo(title2) + assertThat(recTitle3.text).isEqualTo(title3) + assertThat(recSubtitle1.text).isEqualTo(subtitle1) + assertThat(recSubtitle2.text).isEqualTo(subtitle2) + assertThat(recSubtitle3.text).isEqualTo(subtitle3) + } + + @Test + fun bindRecommendation_noTitle_subtitleNotShown() { + player.attachRecommendation(recommendationViewHolder) + + val data = smartspaceData.copy( + recommendations = listOf( + SmartspaceAction.Builder("id1", "") + .setSubtitle("fake subtitle") + .setIcon(Icon.createWithResource(context, R.drawable.ic_1x_mobiledata)) + .setExtras(Bundle.EMPTY) + .build() + ) + ) + player.bindRecommendation(data) + + assertThat(recSubtitle1.text).isEqualTo("") + } + private fun getScrubbingChangeListener(): SeekBarViewModel.ScrubbingChangeListener = withArgCaptor { verify(seekBarViewModel).setScrubbingChangeListener(capture()) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java index eacec20cac12..3e335c5163a9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java @@ -57,7 +57,6 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { private static final String OLD_KEY = "TEST_KEY_OLD"; private static final String APP = "APP"; private static final String PACKAGE = "PKG"; - private static final int BG_COLOR = Color.RED; private static final String ARTIST = "ARTIST"; private static final String TITLE = "TITLE"; private static final String DEVICE_NAME = "DEVICE_NAME"; @@ -76,7 +75,7 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { mManager.addListener(mListener); mMediaData = new MediaData( - USER_ID, true, BG_COLOR, APP, null, ARTIST, TITLE, null, + USER_ID, true, APP, null, ARTIST, TITLE, null, new ArrayList<>(), new ArrayList<>(), null, PACKAGE, null, null, null, true, null, MediaData.PLAYBACK_LOCAL, false, KEY, false, false, false, 0L, InstanceId.fakeInstanceId(-1), -1); diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt index 3b996d4a37d3..1f9490ab3851 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt @@ -20,6 +20,7 @@ import android.app.smartspace.SmartspaceAction import androidx.test.filters.SmallTest import android.testing.AndroidTestingRunner import android.testing.TestableLooper +import com.android.internal.logging.InstanceId import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.broadcast.BroadcastSender @@ -46,7 +47,11 @@ private const val KEY_ALT = "TEST_KEY_2" private const val USER_MAIN = 0 private const val USER_GUEST = 10 private const val PACKAGE = "PKG" +private val INSTANCE_ID = InstanceId.fakeInstanceId(123)!! +private const val APP_UID = 99 private const val SMARTSPACE_KEY = "SMARTSPACE_KEY" +private const val SMARTSPACE_PACKAGE = "SMARTSPACE_PKG" +private val SMARTSPACE_INSTANCE_ID = InstanceId.fakeInstanceId(456)!! @SmallTest @RunWith(AndroidTestingRunner::class) @@ -69,6 +74,8 @@ class MediaDataFilterTest : SysuiTestCase() { private lateinit var smartspaceData: SmartspaceMediaData @Mock private lateinit var smartspaceMediaRecommendationItem: SmartspaceAction + @Mock + private lateinit var logger: MediaUiEventLogger private lateinit var mediaDataFilter: MediaDataFilter private lateinit var dataMain: MediaData @@ -79,8 +86,14 @@ class MediaDataFilterTest : SysuiTestCase() { fun setup() { MockitoAnnotations.initMocks(this) MediaPlayerData.clear() - mediaDataFilter = MediaDataFilter(context, broadcastDispatcher, broadcastSender, - lockscreenUserManager, executor, clock) + mediaDataFilter = MediaDataFilter( + context, + broadcastDispatcher, + broadcastSender, + lockscreenUserManager, + executor, + clock, + logger) mediaDataFilter.mediaDataManager = mediaDataManager mediaDataFilter.addListener(listener) @@ -90,16 +103,19 @@ class MediaDataFilterTest : SysuiTestCase() { // Set up test media data dataMain = MediaTestUtils.emptyMediaData.copy( userId = USER_MAIN, - packageName = PACKAGE) + packageName = PACKAGE, + instanceId = INSTANCE_ID, + appUid = APP_UID) dataGuest = dataMain.copy(userId = USER_GUEST) `when`(smartspaceData.targetId).thenReturn(SMARTSPACE_KEY) `when`(smartspaceData.isActive).thenReturn(true) `when`(smartspaceData.isValid).thenReturn(true) - `when`(smartspaceData.packageName).thenReturn(PACKAGE) + `when`(smartspaceData.packageName).thenReturn(SMARTSPACE_PACKAGE) `when`(smartspaceData.recommendations).thenReturn(listOf(smartspaceMediaRecommendationItem)) `when`(smartspaceData.headphoneConnectionTimeMillis).thenReturn( clock.currentTimeMillis() - 100) + `when`(smartspaceData.instanceId).thenReturn(SMARTSPACE_INSTANCE_ID) } private fun setUser(id: Int) { @@ -241,6 +257,8 @@ class MediaDataFilterTest : SysuiTestCase() { .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true)) assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isTrue() assertThat(mediaDataFilter.hasActiveMedia()).isFalse() + verify(logger).logRecommendationAdded(SMARTSPACE_PACKAGE, SMARTSPACE_INSTANCE_ID) + verify(logger, never()).logRecommendationActivated(any(), any(), any()) } @Test @@ -254,6 +272,8 @@ class MediaDataFilterTest : SysuiTestCase() { verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse() assertThat(mediaDataFilter.hasActiveMedia()).isFalse() + verify(logger, never()).logRecommendationAdded(any(), any()) + verify(logger, never()).logRecommendationActivated(any(), any(), any()) } @Test @@ -267,6 +287,8 @@ class MediaDataFilterTest : SysuiTestCase() { .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true)) assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isTrue() assertThat(mediaDataFilter.hasActiveMedia()).isFalse() + verify(logger).logRecommendationAdded(SMARTSPACE_PACKAGE, SMARTSPACE_INSTANCE_ID) + verify(logger, never()).logRecommendationActivated(any(), any(), any()) } @Test @@ -281,6 +303,8 @@ class MediaDataFilterTest : SysuiTestCase() { verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse() assertThat(mediaDataFilter.hasActiveMedia()).isFalse() + verify(logger, never()).logRecommendationAdded(any(), any()) + verify(logger, never()).logRecommendationActivated(any(), any(), any()) } @Test @@ -302,6 +326,8 @@ class MediaDataFilterTest : SysuiTestCase() { verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse() assertThat(mediaDataFilter.hasActiveMedia()).isFalse() + verify(logger, never()).logRecommendationAdded(any(), any()) + verify(logger, never()).logRecommendationActivated(any(), any(), any()) } @Test @@ -324,6 +350,8 @@ class MediaDataFilterTest : SysuiTestCase() { assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse() // Smartspace update shouldn't be propagated for the empty rec list. verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) + verify(logger, never()).logRecommendationAdded(any(), any()) + verify(logger).logRecommendationActivated(eq(APP_UID), eq(PACKAGE), eq(INSTANCE_ID)) } @Test @@ -345,6 +373,8 @@ class MediaDataFilterTest : SysuiTestCase() { // Smartspace update should also be propagated but not prioritized. verify(listener) .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false)) + verify(logger).logRecommendationAdded(SMARTSPACE_PACKAGE, SMARTSPACE_INSTANCE_ID) + verify(logger).logRecommendationActivated(eq(APP_UID), eq(PACKAGE), eq(INSTANCE_ID)) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt index 68eebede1482..0cbceb6700b4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt @@ -19,6 +19,7 @@ import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import androidx.media.utils.MediaConstants import androidx.test.filters.SmallTest +import com.android.internal.logging.InstanceId import com.android.systemui.InstanceIdSequenceFake import com.android.systemui.R import com.android.systemui.SysuiTestCase @@ -47,6 +48,7 @@ import org.mockito.Mockito import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.verify +import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.junit.MockitoJUnit import org.mockito.Mockito.`when` as whenever @@ -275,6 +277,49 @@ class MediaDataManagerTest : SysuiTestCase() { } @Test + fun testLoadMediaDataInBg_invalidTokenNoCrash() { + val bundle = Bundle() + // wrong data type + bundle.putParcelable(Notification.EXTRA_MEDIA_SESSION, Bundle()) + val rcn = SbnBuilder().run { + setPkg(SYSTEM_PACKAGE_NAME) + modifyNotification(context).also { + it.setSmallIcon(android.R.drawable.ic_media_pause) + it.addExtras(bundle) + it.setStyle(MediaStyle().apply { + setRemotePlaybackInfo("Remote device", 0, null) + }) + } + build() + } + + mediaDataManager.loadMediaDataInBg(KEY, rcn, null) + // no crash even though the data structure is incorrect + } + + @Test + fun testLoadMediaDataInBg_invalidMediaRemoteIntentNoCrash() { + val bundle = Bundle() + // wrong data type + bundle.putParcelable(Notification.EXTRA_MEDIA_REMOTE_INTENT, Bundle()) + val rcn = SbnBuilder().run { + setPkg(SYSTEM_PACKAGE_NAME) + modifyNotification(context).also { + it.setSmallIcon(android.R.drawable.ic_media_pause) + it.addExtras(bundle) + it.setStyle(MediaStyle().apply { + setMediaSession(session.sessionToken) + setRemotePlaybackInfo("Remote device", 0, null) + }) + } + build() + } + + mediaDataManager.loadMediaDataInBg(KEY, rcn, null) + // no crash even though the data structure is incorrect + } + + @Test fun testOnNotificationRemoved_callsListener() { addNotificationAndLoad() val data = mediaDataCaptor.value @@ -452,11 +497,21 @@ class MediaDataManagerTest : SysuiTestCase() { @Test fun testOnSmartspaceMediaDataLoaded_hasNewValidMediaTarget_callsListener() { smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget)) + verify(logger).getNewInstanceId() + val instanceId = instanceIdSequence.lastInstanceId + verify(listener).onSmartspaceMediaDataLoaded( eq(KEY_MEDIA_SMARTSPACE), - eq(SmartspaceMediaData(KEY_MEDIA_SMARTSPACE, true /* isActive */, true /*isValid */, - PACKAGE_NAME, mediaSmartspaceBaseAction, listOf(mediaRecommendationItem), - DISMISS_INTENT, 0, 1234L)), + eq(SmartspaceMediaData( + targetId = KEY_MEDIA_SMARTSPACE, + isActive = true, + isValid = true, + packageName = PACKAGE_NAME, + cardAction = mediaSmartspaceBaseAction, + recommendations = listOf(mediaRecommendationItem), + dismissIntent = DISMISS_INTENT, + headphoneConnectionTimeMillis = 1234L, + instanceId = InstanceId.fakeInstanceId(instanceId))), eq(false)) } @@ -464,12 +519,18 @@ class MediaDataManagerTest : SysuiTestCase() { fun testOnSmartspaceMediaDataLoaded_hasNewInvalidMediaTarget_callsListener() { whenever(mediaSmartspaceTarget.iconGrid).thenReturn(listOf()) smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget)) + verify(logger).getNewInstanceId() + val instanceId = instanceIdSequence.lastInstanceId + verify(listener).onSmartspaceMediaDataLoaded( eq(KEY_MEDIA_SMARTSPACE), - eq(EMPTY_SMARTSPACE_MEDIA_DATA - .copy(targetId = KEY_MEDIA_SMARTSPACE, isActive = true, - isValid = false, dismissIntent = DISMISS_INTENT, - headphoneConnectionTimeMillis = 1234L)), + eq(EMPTY_SMARTSPACE_MEDIA_DATA.copy( + targetId = KEY_MEDIA_SMARTSPACE, + isActive = true, + isValid = false, + dismissIntent = DISMISS_INTENT, + headphoneConnectionTimeMillis = 1234L, + instanceId = InstanceId.fakeInstanceId(instanceId))), eq(false)) } @@ -484,18 +545,25 @@ class MediaDataManagerTest : SysuiTestCase() { whenever(mediaSmartspaceTarget.iconGrid).thenReturn(listOf()) smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget)) + verify(logger).getNewInstanceId() + val instanceId = instanceIdSequence.lastInstanceId verify(listener).onSmartspaceMediaDataLoaded( eq(KEY_MEDIA_SMARTSPACE), - eq(EMPTY_SMARTSPACE_MEDIA_DATA - .copy(targetId = KEY_MEDIA_SMARTSPACE, isActive = true, - isValid = false, dismissIntent = null, headphoneConnectionTimeMillis = 1234L)), + eq(EMPTY_SMARTSPACE_MEDIA_DATA.copy( + targetId = KEY_MEDIA_SMARTSPACE, + isActive = true, + isValid = false, + dismissIntent = null, + headphoneConnectionTimeMillis = 1234L, + instanceId = InstanceId.fakeInstanceId(instanceId))), eq(false)) } @Test fun testOnSmartspaceMediaDataLoaded_hasNoneMediaTarget_notCallsListener() { smartspaceMediaDataProvider.onTargetsAvailable(listOf()) + verify(logger, never()).getNewInstanceId() verify(listener, never()) .onSmartspaceMediaDataLoaded(anyObject(), anyObject(), anyBoolean()) } @@ -503,11 +571,14 @@ class MediaDataManagerTest : SysuiTestCase() { @Test fun testOnSmartspaceMediaDataLoaded_hasNoneMediaTarget_callsRemoveListener() { smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget)) + verify(logger).getNewInstanceId() + smartspaceMediaDataProvider.onTargetsAvailable(listOf()) foregroundExecutor.advanceClockToLast() foregroundExecutor.runAllReady() verify(listener).onSmartspaceMediaDataRemoved(eq(KEY_MEDIA_SMARTSPACE), eq(false)) + verifyNoMoreInteractions(logger) } @Test @@ -809,6 +880,9 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(actions.custom1).isNotNull() assertThat(actions.custom1!!.contentDescription).isEqualTo(customDesc[1]) + + assertThat(actions.reserveNext).isTrue() + assertThat(actions.reservePrev).isTrue() } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaTestUtils.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaTestUtils.kt index c7ef94eb6a64..ae58fe67da23 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaTestUtils.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaTestUtils.kt @@ -7,7 +7,6 @@ class MediaTestUtils { val emptyMediaData = MediaData( userId = 0, initialized = true, - backgroundColor = 0, app = null, appIcon = null, artist = null, diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MetadataAnimationHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MetadataAnimationHandlerTest.kt new file mode 100644 index 000000000000..52cb902a4f38 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MetadataAnimationHandlerTest.kt @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.media + +import org.mockito.Mockito.`when` as whenever +import android.animation.Animator +import android.animation.AnimatorSet +import android.test.suitebuilder.annotation.SmallTest +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import com.android.systemui.SysuiTestCase +import junit.framework.Assert.fail +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.Mockito.times +import org.mockito.Mockito.mock +import org.mockito.Mockito.never +import org.mockito.junit.MockitoJUnit + +@SmallTest +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +class MetadataAnimationHandlerTest : SysuiTestCase() { + + private interface Callback : () -> Unit + private lateinit var handler: MetadataAnimationHandler + + @Mock private lateinit var animatorSet: AnimatorSet + @Mock private lateinit var enterAnimator: Animator + @Mock private lateinit var exitAnimator: Animator + @Mock private lateinit var postExitCB: Callback + @Mock private lateinit var postEnterCB: Callback + + @JvmField @Rule val mockito = MockitoJUnit.rule() + + @Before + fun setUp() { + handler = object : MetadataAnimationHandler(exitAnimator, enterAnimator) { + override fun buildAnimatorSet(exit: Animator, enter: Animator): AnimatorSet { + return animatorSet + } + } + } + + @After + fun tearDown() {} + + @Test + fun firstBind_startsAnimationSet() { + val cb = { fail("Unexpected callback") } + handler.setNext("data-1", cb, cb) + + verify(animatorSet).start() + } + + @Test + fun executeAnimationEnd_runsCallacks() { + handler.setNext("data-1", postExitCB, postEnterCB) + verify(animatorSet, times(1)).start() + verify(postExitCB, never()).invoke() + + handler.onAnimationEnd(exitAnimator) + verify(animatorSet, times(1)).start() + verify(postExitCB, times(1)).invoke() + verify(postEnterCB, never()).invoke() + + handler.onAnimationEnd(enterAnimator) + verify(animatorSet, times(1)).start() + verify(postExitCB, times(1)).invoke() + verify(postEnterCB, times(1)).invoke() + } + + @Test + fun rebindSameData_executesFirstCallback() { + val postExitCB2 = mock(Callback::class.java) + + handler.setNext("data-1", postExitCB, postEnterCB) + handler.setNext("data-1", postExitCB2, postEnterCB) + handler.onAnimationEnd(exitAnimator) + + verify(postExitCB, times(1)).invoke() + verify(postExitCB2, never()).invoke() + verify(postEnterCB, never()).invoke() + } + + @Test + fun rebindDifferentData_executesSecondCallback() { + val postExitCB2 = mock(Callback::class.java) + + handler.setNext("data-1", postExitCB, postEnterCB) + handler.setNext("data-2", postExitCB2, postEnterCB) + handler.onAnimationEnd(exitAnimator) + + verify(postExitCB, never()).invoke() + verify(postExitCB2, times(1)).invoke() + verify(postEnterCB, never()).invoke() + } + + @Test + fun rebindBeforeEnterComplete_animationRestarts() { + val postExitCB2 = mock(Callback::class.java) + val postEnterCB2 = mock(Callback::class.java) + + handler.setNext("data-1", postExitCB, postEnterCB) + verify(animatorSet, times(1)).start() + verify(postExitCB, never()).invoke() + verify(postExitCB2, never()).invoke() + verify(postEnterCB, never()).invoke() + verify(postEnterCB2, never()).invoke() + + whenever(animatorSet.isRunning()).thenReturn(true) + handler.onAnimationEnd(exitAnimator) + verify(animatorSet, times(1)).start() + verify(postExitCB, times(1)).invoke() + verify(postExitCB2, never()).invoke() + verify(postEnterCB, never()).invoke() + verify(postEnterCB2, never()).invoke() + + handler.setNext("data-2", postExitCB2, postEnterCB2) + handler.onAnimationEnd(enterAnimator) + verify(animatorSet, times(2)).start() + verify(postExitCB, times(1)).invoke() + verify(postExitCB2, never()).invoke() + verify(postEnterCB, never()).invoke() + verify(postEnterCB2, never()).invoke() + + handler.onAnimationEnd(exitAnimator) + verify(animatorSet, times(2)).start() + verify(postExitCB, times(1)).invoke() + verify(postExitCB2, times(1)).invoke() + verify(postEnterCB, never()).invoke() + verify(postEnterCB2, never()).invoke() + + handler.onAnimationEnd(enterAnimator) + verify(animatorSet, times(2)).start() + verify(postExitCB, times(1)).invoke() + verify(postExitCB2, times(1)).invoke() + verify(postEnterCB, never()).invoke() + verify(postEnterCB2, times(1)).invoke() + } + + @Test + fun exitAnimationEndMultipleCalls_singleCallbackExecution() { + handler.setNext("data-1", postExitCB, postEnterCB) + handler.onAnimationEnd(exitAnimator) + handler.onAnimationEnd(exitAnimator) + handler.onAnimationEnd(exitAnimator) + + verify(postExitCB, times(1)).invoke() + } + + @Test + fun enterAnimatorEndsWithoutCallback_noAnimatiorStart() { + handler.onAnimationEnd(enterAnimator) + + verify(animatorSet, never()).start() + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt index c48d84698b3b..49be669bb4a5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt @@ -16,6 +16,8 @@ package com.android.systemui.media +import android.animation.Animator +import android.animation.ObjectAnimator import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.View @@ -43,6 +45,7 @@ class SeekBarObserverTest : SysuiTestCase() { private val enabledHeight = 2 private lateinit var observer: SeekBarObserver + @Mock private lateinit var mockSeekbarAnimator: ObjectAnimator @Mock private lateinit var mockHolder: MediaViewHolder @Mock private lateinit var mockSquigglyProgress: SquigglyProgress private lateinit var seekBarView: SeekBar @@ -66,7 +69,11 @@ class SeekBarObserverTest : SysuiTestCase() { whenever(mockHolder.scrubbingElapsedTimeView).thenReturn(scrubbingElapsedTimeView) whenever(mockHolder.scrubbingTotalTimeView).thenReturn(scrubbingTotalTimeView) - observer = SeekBarObserver(mockHolder) + observer = object : SeekBarObserver(mockHolder) { + override fun buildResetAnimator(targetTime: Int): Animator { + return mockSeekbarAnimator + } + } } @Test @@ -189,4 +196,20 @@ class SeekBarObserverTest : SysuiTestCase() { assertThat(scrubbingElapsedTimeView.text).isEqualTo("") assertThat(scrubbingTotalTimeView.text).isEqualTo("") } + + @Test + fun seekBarJumpAnimation() { + val data0 = SeekBarViewModel.Progress(true, true, true, false, 4000, 120000) + val data1 = SeekBarViewModel.Progress(true, true, true, false, 10, 120000) + + // Set initial position of progress bar + observer.onChanged(data0) + assertThat(seekBarView.progress).isEqualTo(4000) + assertThat(seekBarView.max).isEqualTo(120000) + + // Change to second data & confirm no change to position (due to animation delay) + observer.onChanged(data1) + assertThat(seekBarView.progress).isEqualTo(4000) + verify(mockSeekbarAnimator).start() + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/SquigglyProgressTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/SquigglyProgressTest.kt index e3cd90b13422..d087b0fe4413 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/SquigglyProgressTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/SquigglyProgressTest.kt @@ -19,7 +19,7 @@ import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.Captor import org.mockito.Mock -import org.mockito.Mockito.anyFloat +import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit @@ -35,8 +35,7 @@ class SquigglyProgressTest : SysuiTestCase() { lateinit var squigglyProgress: SquigglyProgress @Mock lateinit var canvas: Canvas - @Captor lateinit var wavePaintCaptor: ArgumentCaptor<Paint> - @Captor lateinit var linePaintCaptor: ArgumentCaptor<Paint> + @Captor lateinit var paintCaptor: ArgumentCaptor<Paint> @JvmField @Rule val mockitoRule = MockitoJUnit.rule() @Before @@ -53,9 +52,7 @@ class SquigglyProgressTest : SysuiTestCase() { fun testDrawPathAndLine() { squigglyProgress.draw(canvas) - verify(canvas).drawPath(any(), wavePaintCaptor.capture()) - verify(canvas).drawLine(anyFloat(), anyFloat(), anyFloat(), anyFloat(), - linePaintCaptor.capture()) + verify(canvas, times(2)).drawPath(any(), paintCaptor.capture()) } @Test @@ -69,12 +66,11 @@ class SquigglyProgressTest : SysuiTestCase() { fun testStrokeWidth() { squigglyProgress.draw(canvas) - verify(canvas).drawPath(any(), wavePaintCaptor.capture()) - verify(canvas).drawLine(anyFloat(), anyFloat(), anyFloat(), anyFloat(), - linePaintCaptor.capture()) + verify(canvas, times(2)).drawPath(any(), paintCaptor.capture()) + val (wavePaint, linePaint) = paintCaptor.getAllValues() - assertThat(wavePaintCaptor.value.strokeWidth).isEqualTo(strokeWidth) - assertThat(linePaintCaptor.value.strokeWidth).isEqualTo(strokeWidth) + assertThat(wavePaint.strokeWidth).isEqualTo(strokeWidth) + assertThat(linePaint.strokeWidth).isEqualTo(strokeWidth) } @Test @@ -82,13 +78,12 @@ class SquigglyProgressTest : SysuiTestCase() { squigglyProgress.alpha = alpha squigglyProgress.draw(canvas) - verify(canvas).drawPath(any(), wavePaintCaptor.capture()) - verify(canvas).drawLine(anyFloat(), anyFloat(), anyFloat(), anyFloat(), - linePaintCaptor.capture()) + verify(canvas, times(2)).drawPath(any(), paintCaptor.capture()) + val (wavePaint, linePaint) = paintCaptor.getAllValues() assertThat(squigglyProgress.alpha).isEqualTo(alpha) - assertThat(wavePaintCaptor.value.alpha).isEqualTo(alpha) - assertThat(linePaintCaptor.value.alpha).isEqualTo((alpha / 255f * DISABLED_ALPHA).toInt()) + assertThat(wavePaint.alpha).isEqualTo(alpha) + assertThat(linePaint.alpha).isEqualTo((alpha / 255f * DISABLED_ALPHA).toInt()) } @Test @@ -96,12 +91,11 @@ class SquigglyProgressTest : SysuiTestCase() { squigglyProgress.colorFilter = colorFilter squigglyProgress.draw(canvas) - verify(canvas).drawPath(any(), wavePaintCaptor.capture()) - verify(canvas).drawLine(anyFloat(), anyFloat(), anyFloat(), anyFloat(), - linePaintCaptor.capture()) + verify(canvas, times(2)).drawPath(any(), paintCaptor.capture()) + val (wavePaint, linePaint) = paintCaptor.getAllValues() - assertThat(wavePaintCaptor.value.colorFilter).isEqualTo(colorFilter) - assertThat(linePaintCaptor.value.colorFilter).isEqualTo(colorFilter) + assertThat(wavePaint.colorFilter).isEqualTo(colorFilter) + assertThat(linePaint.colorFilter).isEqualTo(colorFilter) } @Test @@ -109,12 +103,11 @@ class SquigglyProgressTest : SysuiTestCase() { squigglyProgress.setTint(tint) squigglyProgress.draw(canvas) - verify(canvas).drawPath(any(), wavePaintCaptor.capture()) - verify(canvas).drawLine(anyFloat(), anyFloat(), anyFloat(), anyFloat(), - linePaintCaptor.capture()) + verify(canvas, times(2)).drawPath(any(), paintCaptor.capture()) + val (wavePaint, linePaint) = paintCaptor.getAllValues() - assertThat(wavePaintCaptor.value.color).isEqualTo(tint) - assertThat(linePaintCaptor.value.color).isEqualTo( + assertThat(wavePaint.color).isEqualTo(tint) + assertThat(linePaint.color).isEqualTo( ColorUtils.setAlphaComponent(tint, DISABLED_ALPHA)) } }
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt index 067607f9b8ae..9edc4f4c71c3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt @@ -102,7 +102,7 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { TapGestureDetector(context), powerManager, Handler.getMain(), - receiverUiEventLogger, + receiverUiEventLogger ) val callbackCaptor = ArgumentCaptor.forClass(CommandQueue.Callbacks::class.java) @@ -206,6 +206,18 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { assertThat(chipView.getAppIconView().measuredHeight).isEqualTo(expectedSize) } + @Test + fun commandQueueCallback_invalidStateParam_noChipShown() { + commandQueueCallback.updateMediaTapToTransferReceiverDisplay( + StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED, + routeInfo, + null, + APP_NAME + ) + + verify(windowManager, never()).addView(any(), any()) + } + private fun getChipView(): ViewGroup { val viewCaptor = ArgumentCaptor.forClass(View::class.java) verify(windowManager).addView(viewCaptor.capture(), any()) diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java index f5b006d732fd..4a740f6c5571 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java @@ -205,10 +205,9 @@ public class NavigationBarTest extends SysuiTestCase { when(mNavigationBarView.getAccessibilityButton()).thenReturn(mAccessibilityButton); when(mNavigationBarView.getImeSwitchButton()).thenReturn(mImeSwitchButton); when(mNavigationBarView.getBackButton()).thenReturn(mBackButton); - when(mNavigationBarView.getBarTransitions()).thenReturn(mNavigationBarTransitions); when(mNavigationBarView.getRotationButtonController()) .thenReturn(mRotationButtonController); - when(mNavigationBarView.getLightTransitionsController()) + when(mNavigationBarTransitions.getLightTransitionsController()) .thenReturn(mLightBarTransitionsController); when(mStatusBarKeyguardViewManager.isNavBarVisible()).thenReturn(true); setupSysuiDependency(); @@ -459,6 +458,7 @@ public class NavigationBarTest extends SysuiTestCase { mInputMethodManager, mDeadZone, mDeviceConfigProxyFake, + mNavigationBarTransitions, Optional.of(mock(BackAnimation.class)))); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java index 6a2a78b40d2d..084eca82ce98 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTransitionsTest.java @@ -21,7 +21,6 @@ import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; @@ -37,8 +36,8 @@ import com.android.systemui.assist.AssistManager; import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.recents.OverviewProxyService; -import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.phone.BarTransitions; +import com.android.systemui.statusbar.phone.LightBarTransitionsController; import com.android.systemui.statusbar.policy.KeyguardStateController; import org.junit.Before; @@ -53,6 +52,10 @@ import org.mockito.MockitoAnnotations; public class NavigationBarTransitionsTest extends SysuiTestCase { @Mock + LightBarTransitionsController.Factory mLightBarTransitionsFactory; + @Mock + LightBarTransitionsController mLightBarTransitions; + @Mock EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory; @Mock EdgeBackGestureHandler mEdgeBackGestureHandler; @@ -76,10 +79,11 @@ public class NavigationBarTransitionsTest extends SysuiTestCase { .when(mDependency.injectMockDependency(NavigationModeController.class)) .getCurrentUserContext(); + when(mLightBarTransitionsFactory.create(any())).thenReturn(mLightBarTransitions); NavigationBarView navBar = spy(new NavigationBarView(mContext, null)); when(navBar.getCurrentView()).thenReturn(navBar); when(navBar.findViewById(anyInt())).thenReturn(navBar); - mTransitions = new NavigationBarTransitions(navBar, mock(CommandQueue.class)); + mTransitions = new NavigationBarTransitions(navBar, mLightBarTransitionsFactory); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java index b4b459752bc2..e6b960d75215 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java @@ -33,8 +33,12 @@ import static com.android.systemui.people.PeopleSpaceUtils.VALID_CONTACT; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.app.people.ConversationStatus; @@ -44,6 +48,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.content.res.Resources; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Icon; import android.net.Uri; import android.os.UserHandle; @@ -581,6 +586,27 @@ public class PeopleTileViewHelperTest extends SysuiTestCase { } @Test + public void testCreateRemoteViewsWithNotificationContent() throws Exception { + PeopleTileViewHelper helper = spy(getPeopleTileViewHelper(PERSON_TILE)); + doReturn(new BitmapDrawable()).when(helper).resolveImage(any(), any()); + RemoteViews views = helper.getViews(); + View result = views.apply(mContext, null); + + assertEquals(View.VISIBLE, result.findViewById(R.id.image).getVisibility()); + } + + @Test + public void testCreateRemoteViewsWithInvalidNotificationContent() throws Exception { + PeopleTileViewHelper helper = spy(getPeopleTileViewHelper(PERSON_TILE)); + doThrow(SecurityException.class).when(helper).resolveImage(any(), any()); + RemoteViews views = helper.getViews(); + View result = views.apply(mContext, null); + + assertEquals(View.GONE, result.findViewById(R.id.image).getVisibility()); + assertEquals(View.VISIBLE, result.findViewById(R.id.text_content).getVisibility()); + } + + @Test public void testCreateRemoteViewsWithUserQuieted() { PeopleSpaceTile tile = PERSON_TILE.toBuilder() .setIsUserQuieted(true) diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java index 1ffa9dd57aa9..26e4d9dfb003 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java @@ -46,6 +46,7 @@ import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.View; +import com.android.internal.logging.UiEventLogger; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.settingslib.fuelgauge.BatterySaverUtils; import com.android.systemui.SysuiTestCase; @@ -79,6 +80,8 @@ public class PowerNotificationWarningsTest extends SysuiTestCase { @Mock private DialogLaunchAnimator mDialogLaunchAnimator; @Mock + private UiEventLogger mUiEventLogger; + @Mock private View mView; private BroadcastReceiver mReceiver; @@ -101,7 +104,7 @@ public class PowerNotificationWarningsTest extends SysuiTestCase { ActivityStarter starter = mDependency.injectMockDependency(ActivityStarter.class); BroadcastSender broadcastSender = mDependency.injectMockDependency(BroadcastSender.class); mPowerNotificationWarnings = new PowerNotificationWarnings(wrapper, starter, - broadcastSender, () -> mBatteryController, mDialogLaunchAnimator); + broadcastSender, () -> mBatteryController, mDialogLaunchAnimator, mUiEventLogger); BatteryStateSnapshot snapshot = new BatteryStateSnapshot(100, false, false, 1, BatteryManager.BATTERY_HEALTH_GOOD, 5, 15); mPowerNotificationWarnings.updateSnapshot(snapshot); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java index 829445eb92be..a518b808688e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java @@ -190,7 +190,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { QSFragment fragment = resumeAndGetFragment(); enableSplitShade(); setStatusBarState(StatusBarState.KEYGUARD); - when(mQSPanelController.bouncerInTransit()).thenReturn(false); + when(mQSPanelController.isBouncerInTransit()).thenReturn(false); int transitionPxAmount = 123; float transitionProgress = 0.5f; @@ -206,7 +206,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { QSFragment fragment = resumeAndGetFragment(); enableSplitShade(); setStatusBarState(StatusBarState.KEYGUARD); - when(mQSPanelController.bouncerInTransit()).thenReturn(true); + when(mQSPanelController.isBouncerInTransit()).thenReturn(true); int transitionPxAmount = 123; float transitionProgress = 0.5f; @@ -214,7 +214,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { assertThat(mQsFragmentView.getAlpha()) .isEqualTo( - BouncerPanelExpansionCalculator.getBackScrimScaledExpansion( + BouncerPanelExpansionCalculator.aboutToShowBouncerProgress( transitionProgress)); } @@ -315,6 +315,24 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { verify(mQuickQSPanelController).setCollapseExpandAction(action); } + @Test + public void setOverScrollAmount_setsTranslationOnView() { + QSFragment fragment = resumeAndGetFragment(); + + fragment.setOverScrollAmount(123); + + assertThat(mQsFragmentView.getTranslationY()).isEqualTo(123); + } + + @Test + public void setOverScrollAmount_beforeViewCreated_translationIsNotSet() { + QSFragment fragment = getFragment(); + + fragment.setOverScrollAmount(123); + + assertThat(mQsFragmentView.getTranslationY()).isEqualTo(0); + } + @Override protected Fragment instantiate(Context context, String className, Bundle arguments) { MockitoAnnotations.initMocks(this); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt index 689de50d5b4a..69d3f8b313c9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt @@ -61,7 +61,7 @@ class QSPanelControllerTest : SysuiTestCase() { whenever(brightnessSliderFactory.create(any(), any())).thenReturn(brightnessSlider) whenever(brightnessControllerFactory.create(any())).thenReturn(brightnessController) whenever(qsPanel.resources).thenReturn(mContext.orCreateTestableResources.resources) - whenever(statusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(false) + whenever(statusBarKeyguardViewManager.isBouncerInTransit()).thenReturn(false) controller = QSPanelController( qsPanel, @@ -109,10 +109,10 @@ class QSPanelControllerTest : SysuiTestCase() { } @Test - fun testBouncerIsInTransit() { - whenever(statusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(true) - assertThat(controller.bouncerInTransit()).isEqualTo(true) - whenever(statusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(false) - assertThat(controller.bouncerInTransit()).isEqualTo(false) + fun testIsBouncerInTransit() { + whenever(statusBarKeyguardViewManager.isBouncerInTransit()).thenReturn(true) + assertThat(controller.isBouncerInTransit()).isEqualTo(true) + whenever(statusBarKeyguardViewManager.isBouncerInTransit()).thenReturn(false) + assertThat(controller.isBouncerInTransit()).isEqualTo(false) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java index cf97bdae9af2..616f89455c74 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java @@ -21,12 +21,15 @@ import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.View; import android.widget.LinearLayout; +import android.widget.Switch; import android.widget.TextView; import androidx.recyclerview.widget.RecyclerView; import androidx.test.filters.SmallTest; +import com.android.dx.mockito.inline.extended.ExtendedMockito; import com.android.internal.logging.UiEventLogger; +import com.android.settingslib.wifi.WifiEnterpriseRestrictionUtils; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -42,6 +45,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.mockito.MockitoSession; import java.util.List; @@ -79,12 +83,16 @@ public class InternetDialogTest extends SysuiTestCase { private LinearLayout mEthernet; private LinearLayout mMobileDataToggle; private LinearLayout mWifiToggle; + private Switch mWifiToggleSwitch; + private TextView mWifiToggleSummary; private LinearLayout mConnectedWifi; private RecyclerView mWifiList; private LinearLayout mSeeAll; private LinearLayout mWifiScanNotify; private TextView mAirplaneModeSummaryText; + private MockitoSession mMockitoSession; + @Before public void setUp() { MockitoAnnotations.initMocks(this); @@ -101,6 +109,15 @@ public class InternetDialogTest extends SysuiTestCase { .thenReturn(MOBILE_NETWORK_SUMMARY); when(mInternetDialogController.getWifiManager()).thenReturn(mWifiManager); + mMockitoSession = ExtendedMockito.mockitoSession() + .spyStatic(WifiEnterpriseRestrictionUtils.class) + .startMocking(); + when(WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(mContext)).thenReturn(true); + + createInternetDialog(); + } + + private void createInternetDialog() { mInternetDialog = new InternetDialog(mContext, mock(InternetDialogFactory.class), mInternetDialogController, true, true, true, mock(UiEventLogger.class), mHandler, mBgExecutor, mKeyguard); @@ -114,6 +131,8 @@ public class InternetDialogTest extends SysuiTestCase { mEthernet = mDialogView.requireViewById(R.id.ethernet_layout); mMobileDataToggle = mDialogView.requireViewById(R.id.mobile_network_layout); mWifiToggle = mDialogView.requireViewById(R.id.turn_on_wifi_layout); + mWifiToggleSwitch = mDialogView.requireViewById(R.id.wifi_toggle); + mWifiToggleSummary = mDialogView.requireViewById(R.id.wifi_toggle_summary); mConnectedWifi = mDialogView.requireViewById(R.id.wifi_connected_layout); mWifiList = mDialogView.requireViewById(R.id.wifi_list_layout); mSeeAll = mDialogView.requireViewById(R.id.see_all_layout); @@ -124,6 +143,7 @@ public class InternetDialogTest extends SysuiTestCase { @After public void tearDown() { mInternetDialog.dismissDialog(); + mMockitoSession.finishMocking(); } @Test @@ -411,6 +431,33 @@ public class InternetDialogTest extends SysuiTestCase { } @Test + public void updateDialog_disallowChangeWifiState_disableWifiSwitch() { + mInternetDialog.dismissDialog(); + when(WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(mContext)).thenReturn(false); + createInternetDialog(); + + mInternetDialog.updateDialog(false); + + // Disable Wi-Fi switch and show restriction message in summary. + assertThat(mWifiToggleSwitch.isEnabled()).isFalse(); + assertThat(mWifiToggleSummary.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mWifiToggleSummary.getText().length()).isNotEqualTo(0); + } + + @Test + public void updateDialog_allowChangeWifiState_enableWifiSwitch() { + mInternetDialog.dismissDialog(); + when(WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(mContext)).thenReturn(true); + createInternetDialog(); + + mInternetDialog.updateDialog(false); + + // Enable Wi-Fi switch and hide restriction message in summary. + assertThat(mWifiToggleSwitch.isEnabled()).isTrue(); + assertThat(mWifiToggleSummary.getVisibility()).isEqualTo(View.GONE); + } + + @Test public void updateDialog_wifiOn_hideWifiScanNotify() { // The preconditions WiFi ON and WiFi entries are already in setUp() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java index 03c22b32b8f6..1b1f4e41f200 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java @@ -32,6 +32,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; +import android.app.Notification; import android.content.Context; import android.content.ContextWrapper; import android.content.pm.ApplicationInfo; @@ -41,6 +42,7 @@ import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Icon; +import android.os.Bundle; import android.os.UserHandle; import android.service.notification.StatusBarNotification; @@ -170,4 +172,16 @@ public class StatusBarIconViewTest extends SysuiTestCase { mIconView.getIcon(largeIcon); // No crash? good } + + @Test + public void testContentDescForNotification_invalidAi_noCrash() { + Notification n = new Notification.Builder(mContext, "test") + .setSmallIcon(0) + .build(); + // should be ApplicationInfo + n.extras.putParcelable(Notification.EXTRA_BUILDER_APPLICATION_INFO, new Bundle()); + StatusBarIconView.contentDescForNotification(mContext, n); + + // no crash, good + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java index 241451edf698..5804ad425267 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java @@ -229,6 +229,41 @@ public class NotificationEntryTest extends SysuiTestCase { assertTrue(entry.isLastMessageFromReply()); } + @Test + public void notificationDataEntry_testIsLastMessageFromReply_invalidPerson_noCrash() { + Person.Builder person = new Person.Builder() + .setName("name") + .setKey("abc") + .setUri("uri") + .setBot(true); + + Bundle bundle = new Bundle(); + // should be Person.class + bundle.putParcelable(Notification.EXTRA_MESSAGING_PERSON, new Bundle()); + Bundle[] messagesBundle = new Bundle[]{new Notification.MessagingStyle.Message( + "text", 0, person.build()).toBundle()}; + bundle.putParcelableArray(Notification.EXTRA_MESSAGES, messagesBundle); + + Notification notification = new Notification.Builder(mContext, "test") + .addExtras(bundle) + .build(); + + NotificationEntry entry = new NotificationEntryBuilder() + .setPkg("pkg") + .setOpPkg("pkg") + .setTag("tag") + .setNotification(notification) + .setUser(mContext.getUser()) + .setOverrideGroupKey("") + .build(); + entry.setHasSentReply(); + + entry.isLastMessageFromReply(); + + // no crash, good + } + + private Notification.Action createContextualAction(String title) { return new Notification.Action.Builder( Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon), diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java index 324f0ac08fad..b1f10751119e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java @@ -44,12 +44,15 @@ import android.app.INotificationManager; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationChannelGroup; +import android.app.PendingIntent; +import android.app.Person; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.graphics.drawable.Drawable; import android.os.UserHandle; import android.service.notification.StatusBarNotification; +import android.telecom.TelecomManager; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -116,11 +119,15 @@ public class NotificationInfoTest extends SysuiTestCase { private ChannelEditorDialogController mChannelEditorDialogController; @Mock private AssistantFeedbackController mAssistantFeedbackController; + @Mock + private TelecomManager mTelecomManager; @Before public void setUp() throws Exception { mTestableLooper = TestableLooper.get(this); + mContext.addMockSystemService(TelecomManager.class, mTelecomManager); + mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper()); mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger); // Inflate the layout @@ -161,7 +168,7 @@ public class NotificationInfoTest extends SysuiTestCase { IMPORTANCE_LOW); mDefaultNotificationChannelSet.add(mDefaultNotificationChannel); mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0, - new Notification(), UserHandle.CURRENT, null, 0); + new Notification(), UserHandle.getUserHandleForUid(TEST_UID), null, 0); mEntry = new NotificationEntryBuilder().setSbn(mSbn).build(); when(mAssistantFeedbackController.isFeedbackEnabled()).thenReturn(false); when(mAssistantFeedbackController.getInlineDescriptionResource(any())) @@ -632,6 +639,92 @@ public class NotificationInfoTest extends SysuiTestCase { } @Test + public void testBindNotification_whenCurrentlyInCall() throws Exception { + when(mMockINotificationManager.isInCall(anyString(), anyInt())).thenReturn(true); + + Person person = new Person.Builder() + .setName("caller") + .build(); + Notification.Builder nb = new Notification.Builder( + mContext, mNotificationChannel.getId()) + .setContentTitle("foo") + .setSmallIcon(android.R.drawable.sym_def_app_icon) + .setStyle(Notification.CallStyle.forOngoingCall( + person, mock(PendingIntent.class))) + .setFullScreenIntent(mock(PendingIntent.class), true) + .addAction(new Notification.Action.Builder(null, "test", null).build()); + + mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0, + nb.build(), UserHandle.getUserHandleForUid(TEST_UID), null, 0); + mEntry.setSbn(mSbn); + mNotificationInfo.bindNotification( + mMockPackageManager, + mMockINotificationManager, + mOnUserInteractionCallback, + mChannelEditorDialogController, + TEST_PACKAGE_NAME, + mNotificationChannel, + mNotificationChannelSet, + mEntry, + null, + null, + mUiEventLogger, + true, + false, + true, + mAssistantFeedbackController); + final TextView view = mNotificationInfo.findViewById(R.id.non_configurable_call_text); + assertEquals(View.VISIBLE, view.getVisibility()); + assertEquals(mContext.getString(R.string.notification_unblockable_call_desc), + view.getText()); + assertEquals(GONE, + mNotificationInfo.findViewById(R.id.interruptiveness_settings).getVisibility()); + assertEquals(GONE, + mNotificationInfo.findViewById(R.id.non_configurable_text).getVisibility()); + } + + @Test + public void testBindNotification_whenCurrentlyInCall_notCall() throws Exception { + when(mMockINotificationManager.isInCall(anyString(), anyInt())).thenReturn(true); + + Person person = new Person.Builder() + .setName("caller") + .build(); + Notification.Builder nb = new Notification.Builder( + mContext, mNotificationChannel.getId()) + .setContentTitle("foo") + .setSmallIcon(android.R.drawable.sym_def_app_icon) + .setFullScreenIntent(mock(PendingIntent.class), true) + .addAction(new Notification.Action.Builder(null, "test", null).build()); + + mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0, + nb.build(), UserHandle.getUserHandleForUid(TEST_UID), null, 0); + mEntry.setSbn(mSbn); + mNotificationInfo.bindNotification( + mMockPackageManager, + mMockINotificationManager, + mOnUserInteractionCallback, + mChannelEditorDialogController, + TEST_PACKAGE_NAME, + mNotificationChannel, + mNotificationChannelSet, + mEntry, + null, + null, + mUiEventLogger, + true, + false, + true, + mAssistantFeedbackController); + assertEquals(GONE, + mNotificationInfo.findViewById(R.id.non_configurable_call_text).getVisibility()); + assertEquals(VISIBLE, + mNotificationInfo.findViewById(R.id.interruptiveness_settings).getVisibility()); + assertEquals(GONE, + mNotificationInfo.findViewById(R.id.non_configurable_text).getVisibility()); + } + + @Test public void testBindNotification_automaticIsVisible() throws Exception { when(mAssistantFeedbackController.isFeedbackEnabled()).thenReturn(true); mNotificationInfo.bindNotification( diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapperTest.java new file mode 100644 index 000000000000..509ba4194e5e --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapperTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.notification.row.wrapper; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.app.Notification; +import android.content.Context; +import android.graphics.drawable.Icon; +import android.os.Bundle; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; +import android.testing.TestableLooper.RunWithLooper; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; +import com.android.systemui.statusbar.notification.row.NotificationTestHelper; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidTestingRunner.class) +@SmallTest +@RunWithLooper +public class NotificationBigPictureTemplateViewWrapperTest extends SysuiTestCase { + + private View mView; + private ExpandableNotificationRow mRow; + + + @Before + public void setup() throws Exception { + allowTestableLooperAsMainThread(); + NotificationTestHelper helper = new NotificationTestHelper( + mContext, + mDependency, + TestableLooper.get(this)); + mView = LayoutInflater.from(mContext).inflate( + com.android.internal.R.layout.notification_template_material_big_picture, null); + mRow = helper.createRow(); + } + + @Test + public void invalidLargeIconBig_noCrash() { + NotificationViewWrapper wrapper = new NotificationBigPictureTemplateViewWrapper( + mContext, mView, mRow); + // should be Icon.class + mRow.getEntry().getSbn().getNotification().setSmallIcon( + Icon.createWithResource(mContext, 0)); + mRow.getEntry().getSbn().getNotification().extras.putParcelable( + Notification.EXTRA_LARGE_ICON_BIG, new Bundle()); + wrapper.onContentUpdated(mRow); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt index 5d160366b27d..4270d72770dc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt @@ -144,7 +144,7 @@ class NotificationShelfTest : SysuiTestCase() { } private fun setFractionToShade(fraction: Float) { - shelf.setFractionToShade(fraction) + whenever(ambientState.fractionToShade).thenReturn(fraction) } private fun setOnLockscreen(isOnLockscreen: Boolean) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index 7a92b96f40db..077f6bfc5f31 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -64,6 +64,7 @@ import com.android.systemui.statusbar.notification.row.FooterView; import com.android.systemui.statusbar.phone.CentralSurfaces; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.ShadeController; +import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController; import org.junit.Assert; @@ -104,6 +105,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; @Mock private NotificationShelf mNotificationShelf; @Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator; + @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; @Before @UiThreadTest @@ -111,7 +113,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { allowTestableLooperAsMainThread(); // Interact with real instance of AmbientState. - mAmbientState = new AmbientState(mContext, mNotificationSectionsManager, mBypassController); + mAmbientState = new AmbientState(mContext, mNotificationSectionsManager, mBypassController, + mStatusBarKeyguardViewManager); // Inject dependencies before initializing the layout mDependency.injectTestDependency(SysuiStatusBarStateController.class, mBarState); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt index dfd70a2e810b..c3658ba11b2d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt @@ -16,17 +16,21 @@ package com.android.systemui.statusbar.notification.stack +import android.annotation.DimenRes import android.service.notification.StatusBarNotification import android.testing.AndroidTestingRunner import android.view.View.VISIBLE import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase +import com.android.systemui.statusbar.LockscreenShadeTransitionController +import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.notification.row.ExpandableView import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.nullable import com.google.common.truth.Truth.assertThat import org.junit.Before @@ -34,41 +38,40 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito.mock -import org.mockito.MockitoAnnotations import org.mockito.Mockito.`when` as whenever +import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidTestingRunner::class) class NotificationStackSizeCalculatorTest : SysuiTestCase() { @Mock private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController - + @Mock private lateinit var lockscreenShadeTransitionController: LockscreenShadeTransitionController @Mock private lateinit var stackLayout: NotificationStackScrollLayout private val testableResources = mContext.getOrCreateTestableResources() private lateinit var sizeCalculator: NotificationStackSizeCalculator + private val gapHeight = px(R.dimen.notification_section_divider_height) + private val dividerHeight = px(R.dimen.notification_divider_height) + private val shelfHeight = px(R.dimen.notification_shelf_height) + private val rowHeight = px(R.dimen.notification_max_height) + @Before fun setUp() { MockitoAnnotations.initMocks(this) - whenever(stackLayout.calculateGapHeight(nullable(), nullable(), any())) - .thenReturn(GAP_HEIGHT) - with(testableResources) { - addOverride(R.integer.keyguard_max_notification_count, -1) - addOverride(R.dimen.notification_divider_height, DIVIDER_HEIGHT.toInt()) - } - sizeCalculator = NotificationStackSizeCalculator( statusBarStateController = sysuiStatusBarStateController, + lockscreenShadeTransitionController = lockscreenShadeTransitionController, testableResources.resources) } @Test fun computeMaxKeyguardNotifications_zeroSpace_returnZero() { - val rows = listOf(createMockRow(height = ROW_HEIGHT)) + val rows = listOf(createMockRow(height = rowHeight)) val maxNotifications = computeMaxKeyguardNotifications(rows, availableSpace = 0f, shelfHeight = 0f) @@ -87,105 +90,127 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() { } @Test - fun computeMaxKeyguardNotifications_spaceForOne_returnsOne() { - val rowHeight = ROW_HEIGHT - val totalSpaceForEachRow = GAP_HEIGHT + rowHeight - val shelfHeight = - totalSpaceForEachRow / 2 // In this way shelf absence will not leave room for another. - val spaceForOne = totalSpaceForEachRow - val rows = - listOf( - createMockRow(rowHeight), - createMockRow(rowHeight)) - - val maxNotifications = - computeMaxKeyguardNotifications( - rows, availableSpace = spaceForOne, shelfHeight = shelfHeight) + fun computeMaxKeyguardNotifications_spaceForOneAndShelf_returnsOne() { + setGapHeight(gapHeight) + val shelfHeight = rowHeight / 2 // Shelf absence won't leave room for another row. + val availableSpace = + listOf(rowHeight + dividerHeight, gapHeight + dividerHeight + shelfHeight).sum() + val rows = listOf(createMockRow(rowHeight), createMockRow(rowHeight)) - assertThat(maxNotifications).isEqualTo(1) - } - - @Test - fun computeMaxKeyguardNotifications_spaceForOne_shelfUsableForLastNotification_returnsTwo() { - val rowHeight = ROW_HEIGHT - val totalSpaceForEachRow = GAP_HEIGHT + rowHeight - val shelfHeight = totalSpaceForEachRow + DIVIDER_HEIGHT - val spaceForOne = totalSpaceForEachRow - val rows = - listOf( - createMockRow(rowHeight), - createMockRow(rowHeight)) - - val maxNotifications = - computeMaxKeyguardNotifications( - rows, availableSpace = spaceForOne, shelfHeight = shelfHeight) + val maxNotifications = computeMaxKeyguardNotifications(rows, availableSpace, shelfHeight) assertThat(maxNotifications).isEqualTo(1) } @Test fun computeMaxKeyguardNotifications_spaceForTwo_returnsTwo() { - val rowHeight = ROW_HEIGHT - val totalSpaceForEachRow = GAP_HEIGHT + rowHeight - val spaceForTwo = totalSpaceForEachRow * 2 + DIVIDER_HEIGHT - val rows = + setGapHeight(gapHeight) + val shelfHeight = shelfHeight + dividerHeight + val availableSpace = listOf( - createMockRow(rowHeight), - createMockRow(rowHeight), - createMockRow(rowHeight)) + rowHeight + dividerHeight, + gapHeight + rowHeight + dividerHeight, + gapHeight + dividerHeight + shelfHeight) + .sum() + val rows = + listOf(createMockRow(rowHeight), createMockRow(rowHeight), createMockRow(rowHeight)) - val maxNotifications = computeMaxKeyguardNotifications(rows, spaceForTwo, shelfHeight = 0f) + val maxNotifications = computeMaxKeyguardNotifications(rows, availableSpace, shelfHeight) assertThat(maxNotifications).isEqualTo(2) } @Test fun computeHeight_returnsAtMostSpaceAvailable_withGapBeforeShelf() { - val rowHeight = ROW_HEIGHT - val shelfHeight = SHELF_HEIGHT - val totalSpaceForEachRow = GAP_HEIGHT + rowHeight + DIVIDER_HEIGHT - val availableSpace = totalSpaceForEachRow * 2 + setGapHeight(gapHeight) + val shelfHeight = shelfHeight + val availableSpace = + listOf( + rowHeight + dividerHeight, + gapHeight + rowHeight + dividerHeight, + gapHeight + dividerHeight + shelfHeight) + .sum() // All rows in separate sections (default setup). val rows = - listOf( - createMockRow(rowHeight), - createMockRow(rowHeight), - createMockRow(rowHeight)) + listOf(createMockRow(rowHeight), createMockRow(rowHeight), createMockRow(rowHeight)) val maxNotifications = computeMaxKeyguardNotifications(rows, availableSpace, shelfHeight) assertThat(maxNotifications).isEqualTo(2) - val height = sizeCalculator.computeHeight(stackLayout, maxNotifications, SHELF_HEIGHT) - assertThat(height).isAtMost(availableSpace + GAP_HEIGHT + SHELF_HEIGHT) + val height = sizeCalculator.computeHeight(stackLayout, maxNotifications, this.shelfHeight) + assertThat(height).isAtMost(availableSpace) } @Test - fun computeHeight_returnsAtMostSpaceAvailable_noGapBeforeShelf() { - val rowHeight = ROW_HEIGHT - val shelfHeight = SHELF_HEIGHT - val totalSpaceForEachRow = GAP_HEIGHT + rowHeight + DIVIDER_HEIGHT - val availableSpace = totalSpaceForEachRow * 1 - + fun computeHeight_noGapBeforeShelf_returnsAtMostSpaceAvailable() { // Both rows are in the same section. - whenever(stackLayout.calculateGapHeight(nullable(), nullable(), any())) - .thenReturn(0f) - val rows = - listOf( - createMockRow(rowHeight), - createMockRow(rowHeight)) + setGapHeight(0f) + val rowHeight = rowHeight + val shelfHeight = shelfHeight + val availableSpace = listOf(rowHeight + dividerHeight, dividerHeight + shelfHeight).sum() + val rows = listOf(createMockRow(rowHeight), createMockRow(rowHeight)) val maxNotifications = computeMaxKeyguardNotifications(rows, availableSpace, shelfHeight) assertThat(maxNotifications).isEqualTo(1) - val height = sizeCalculator.computeHeight(stackLayout, maxNotifications, SHELF_HEIGHT) - assertThat(height).isAtMost(availableSpace + SHELF_HEIGHT) + val height = sizeCalculator.computeHeight(stackLayout, maxNotifications, this.shelfHeight) + assertThat(height).isAtMost(availableSpace) + } + + @Test + fun onLockscreen_onKeyguard_AndNotGoingToShade_returnsTrue() { + whenever(sysuiStatusBarStateController.state).thenReturn(StatusBarState.KEYGUARD) + whenever(lockscreenShadeTransitionController.fractionToShade).thenReturn(0f) + assertThat(sizeCalculator.onLockscreen()).isTrue() + } + + @Test + fun onLockscreen_goingToShade_returnsFalse() { + whenever(sysuiStatusBarStateController.state).thenReturn(StatusBarState.KEYGUARD) + whenever(lockscreenShadeTransitionController.fractionToShade).thenReturn(0.5f) + assertThat(sizeCalculator.onLockscreen()).isFalse() + } + + @Test + fun onLockscreen_notOnLockscreen_returnsFalse() { + whenever(sysuiStatusBarStateController.state).thenReturn(StatusBarState.SHADE) + whenever(lockscreenShadeTransitionController.fractionToShade).thenReturn(1f) + assertThat(sizeCalculator.onLockscreen()).isFalse() + } + + @Test + fun spaceNeeded_onLockscreen_usesMinHeight() { + setGapHeight(0f) + // No divider height since we're testing one element where index = 0 + + val expandableView = createMockRow(rowHeight) + whenever(expandableView.getMinHeight(any())).thenReturn(5) + whenever(expandableView.intrinsicHeight).thenReturn(10) + + val space = sizeCalculator.spaceNeeded(expandableView, visibleIndex = 0, + previousView = null, stack = stackLayout, onLockscreen = true) + assertThat(space).isEqualTo(5) + } + + @Test + fun spaceNeeded_notOnLockscreen_usesIntrinsicHeight() { + setGapHeight(0f) + // No divider height since we're testing one element where index = 0 + + val expandableView = createMockRow(rowHeight) + whenever(expandableView.getMinHeight(any())).thenReturn(5) + whenever(expandableView.intrinsicHeight).thenReturn(10) + + val space = sizeCalculator.spaceNeeded(expandableView, visibleIndex = 0, + previousView = null, stack = stackLayout, onLockscreen = false) + assertThat(space).isEqualTo(10) } private fun computeMaxKeyguardNotifications( rows: List<ExpandableView>, availableSpace: Float, - shelfHeight: Float = SHELF_HEIGHT + shelfHeight: Float = this.shelfHeight ): Int { setupChildren(rows) return sizeCalculator.computeMaxKeyguardNotifications( @@ -204,9 +229,9 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() { (1..number).map { createMockRow() }.toList() private fun createMockRow( - height: Float = ROW_HEIGHT, + height: Float = rowHeight, isRemoved: Boolean = false, - visibility: Int = VISIBLE, + visibility: Int = VISIBLE ): ExpandableNotificationRow { val row = mock(ExpandableNotificationRow::class.java) val entry = mock(NotificationEntry::class.java) @@ -220,11 +245,12 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() { return row } - /** Default dimensions for tests that don't overwrite them. */ - companion object { - const val GAP_HEIGHT = 12f - const val DIVIDER_HEIGHT = 3f - const val SHELF_HEIGHT = 14f - const val ROW_HEIGHT = SHELF_HEIGHT * 3 + private fun setGapHeight(height: Float) { + whenever(stackLayout.calculateGapHeight(nullable(), nullable(), any())).thenReturn(height) + whenever(stackLayout.calculateGapHeight(nullable(), nullable(), /* visibleIndex= */ eq(0))) + .thenReturn(0f) } + + private fun px(@DimenRes id: Int): Float = + testableResources.resources.getDimensionPixelSize(id).toFloat() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt index 1da9bbcdb836..1f90d0cf9494 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt @@ -1,5 +1,6 @@ package com.android.systemui.statusbar.notification.stack +import android.annotation.DimenRes import android.widget.FrameLayout import androidx.test.filters.SmallTest import com.android.systemui.R @@ -8,6 +9,7 @@ import com.android.systemui.statusbar.EmptyShadeView import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.BypassController import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.SectionProvider +import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test @@ -21,10 +23,22 @@ class StackScrollAlgorithmTest : SysuiTestCase() { private val stackScrollAlgorithm = StackScrollAlgorithm(context, hostView) private val expandableViewState = ExpandableViewState() private val notificationRow = mock(ExpandableNotificationRow::class.java) + private val mStatusBarKeyguardViewManager = mock(StatusBarKeyguardViewManager::class.java) + private val ambientState = AmbientState( - context, - SectionProvider { _, _ -> false }, - BypassController { false }) + context, + SectionProvider { _, _ -> false }, + BypassController { false }, + mStatusBarKeyguardViewManager + ) + + private val testableResources = mContext.orCreateTestableResources + + private fun px(@DimenRes id: Int): Float = + testableResources.resources.getDimensionPixelSize(id).toFloat() + + private val bigGap = px(R.dimen.notification_section_divider_height) + private val smallGap = px(R.dimen.notification_section_divider_height_lockscreen) @Before fun setUp() { @@ -75,4 +89,25 @@ class StackScrollAlgorithmTest : SysuiTestCase() { val centeredY = ambientState.stackY + fullHeight / 2f - emptyShadeView.height / 2f assertThat(emptyShadeView.viewState?.yTranslation).isEqualTo(centeredY) } + + @Test + fun getGapForLocation_onLockscreen_returnsSmallGap() { + val gap = stackScrollAlgorithm.getGapForLocation( + /* fractionToShade= */ 0f, /* onKeyguard= */ true) + assertThat(gap).isEqualTo(smallGap) + } + + @Test + fun getGapForLocation_goingToShade_interpolatesGap() { + val gap = stackScrollAlgorithm.getGapForLocation( + /* fractionToShade= */ 0.5f, /* onKeyguard= */ true) + assertThat(gap).isEqualTo(smallGap * 0.5f + bigGap * 0.5f) + } + + @Test + fun getGapForLocation_notOnLockscreen_returnsBigGap() { + val gap = stackScrollAlgorithm.getGapForLocation( + /* fractionToShade= */ 0f, /* onKeyguard= */ false) + assertThat(gap).isEqualTo(bigGap) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java index 0e12c2adc09a..03a6c19dc86a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java @@ -58,6 +58,7 @@ import com.android.systemui.statusbar.policy.CastController.CastDevice; import com.android.systemui.statusbar.policy.DataSaverController; import com.android.systemui.statusbar.policy.DeviceControlsController; import com.android.systemui.statusbar.policy.HotspotController; +import com.android.systemui.statusbar.policy.SafetyController; import com.android.systemui.statusbar.policy.WalletController; import com.android.systemui.util.settings.FakeSettings; import com.android.systemui.util.settings.SecureSettings; @@ -101,6 +102,7 @@ public class AutoTileManagerTest extends SysuiTestCase { @Mock private ReduceBrightColorsController mReduceBrightColorsController; @Mock private DeviceControlsController mDeviceControlsController; @Mock private WalletController mWalletController; + @Mock private SafetyController mSafetyController; @Mock(answer = Answers.RETURNS_SELF) private AutoAddTracker.Builder mAutoAddTrackerBuilder; @Mock private Context mUserContext; @@ -150,6 +152,7 @@ public class AutoTileManagerTest extends SysuiTestCase { ReduceBrightColorsController reduceBrightColorsController, DeviceControlsController deviceControlsController, WalletController walletController, + SafetyController safetyController, @Named(RBC_AVAILABLE) boolean isReduceBrightColorsAvailable) { return new AutoTileManager(context, autoAddTrackerBuilder, mQsTileHost, Handler.createAsync(TestableLooper.get(this).getLooper()), @@ -162,6 +165,7 @@ public class AutoTileManagerTest extends SysuiTestCase { reduceBrightColorsController, deviceControlsController, walletController, + safetyController, isReduceBrightColorsAvailable); } @@ -169,7 +173,7 @@ public class AutoTileManagerTest extends SysuiTestCase { return createAutoTileManager(context, mAutoAddTrackerBuilder, mHotspotController, mDataSaverController, mManagedProfileController, mNightDisplayListener, mCastController, mReduceBrightColorsController, mDeviceControlsController, - mWalletController, mIsReduceBrightColorsAvailable); + mWalletController, mSafetyController, mIsReduceBrightColorsAvailable); } @Test @@ -185,10 +189,11 @@ public class AutoTileManagerTest extends SysuiTestCase { ReduceBrightColorsController rBC = mock(ReduceBrightColorsController.class); DeviceControlsController dCC = mock(DeviceControlsController.class); WalletController wC = mock(WalletController.class); + SafetyController sC = mock(SafetyController.class); AutoTileManager manager = createAutoTileManager(mock(Context.class), builder, hC, dSC, mPC, nDS, cC, rBC, - dCC, wC, true); + dCC, wC, sC, true); verify(tracker, never()).initialize(); verify(hC, never()).addCallback(any()); @@ -199,6 +204,7 @@ public class AutoTileManagerTest extends SysuiTestCase { verify(rBC, never()).addCallback(any()); verify(dCC, never()).setCallback(any()); verify(wC, never()).getWalletPosition(); + verify(sC, never()).addCallback(any()); assertNull(manager.getSecureSettingForKey(TEST_SETTING)); assertNull(manager.getSecureSettingForKey(TEST_SETTING_COMPONENT)); } @@ -253,6 +259,10 @@ public class AutoTileManagerTest extends SysuiTestCase { verify(mWalletController, times(2)).getWalletPosition(); + InOrder inOrderSafety = inOrder(mSafetyController); + inOrderSafety.verify(mSafetyController).removeCallback(any()); + inOrderSafety.verify(mSafetyController).addCallback(any()); + SettingObserver setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING); assertEquals(USER + 1, setting.getCurrentUser()); assertTrue(setting.isListening()); @@ -303,6 +313,10 @@ public class AutoTileManagerTest extends SysuiTestCase { verify(mWalletController, times(2)).getWalletPosition(); + InOrder inOrderSafety = inOrder(mSafetyController); + inOrderSafety.verify(mSafetyController).removeCallback(any()); + inOrderSafety.verify(mSafetyController).addCallback(any()); + SettingObserver setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING); assertEquals(USER + 1, setting.getCurrentUser()); assertFalse(setting.isListening()); @@ -457,6 +471,26 @@ public class AutoTileManagerTest extends SysuiTestCase { mAutoTileManager.changeUser(UserHandle.of(USER + 1)); verify(mQsTileHost, times(2)).addTile(safetyComponent, true); } + + @Test + public void testSafetyTileRemoved_onSafetyCenterDisable() { + ComponentName safetyComponent = CustomTile.getComponentFromSpec(TEST_CUSTOM_SAFETY_SPEC); + mAutoTileManager.init(); + when(mAutoAddTracker.isAdded(TEST_CUSTOM_SAFETY_SPEC)).thenReturn(true); + mAutoTileManager.mSafetyCallback.onSafetyCenterEnableChanged(false); + verify(mQsTileHost, times(1)).removeTile(safetyComponent); + } + + @Test + public void testSafetyTileAdded_onSafetyCenterEnable() { + ComponentName safetyComponent = CustomTile.getComponentFromSpec(TEST_CUSTOM_SAFETY_SPEC); + mAutoTileManager.init(); + verify(mQsTileHost, times(1)).addTile(safetyComponent, true); + mAutoTileManager.mSafetyCallback.onSafetyCenterEnableChanged(false); + mAutoTileManager.mSafetyCallback.onSafetyCenterEnableChanged(true); + verify(mQsTileHost, times(2)).addTile(safetyComponent, true); + } + @Test public void testEmptyArray_doesNotCrash() { mContext.getOrCreateTestableResources().addOverride( diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java index 5f2bbd341962..077b41a0aa90 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java @@ -126,6 +126,12 @@ public class DozeParametersTest extends SysuiTestCase { setAodEnabledForTest(true); setShouldControlUnlockedScreenOffForTest(true); setDisplayNeedsBlankingForTest(false); + + // Default to false here (with one test to make sure that when it returns true, we respect + // that). We'll test the specific conditions for this to return true/false in the + // UnlockedScreenOffAnimationController's tests. + when(mUnlockedScreenOffAnimationController.shouldPlayUnlockedScreenOffAnimation()) + .thenReturn(false); } @Test @@ -174,9 +180,12 @@ public class DozeParametersTest extends SysuiTestCase { */ @Test public void testControlUnlockedScreenOffAnimation_dozeAfterScreenOff_false() { + mDozeParameters.mKeyguardVisibilityCallback.onKeyguardVisibilityChanged(true); + // If AOD is disabled, we shouldn't want to control screen off. Also, let's double check // that when that value is updated, we called through to PowerManager. setAodEnabledForTest(false); + assertFalse(mDozeParameters.shouldControlScreenOff()); assertTrue(mPowerManagerDozeAfterScreenOff); @@ -188,7 +197,6 @@ public class DozeParametersTest extends SysuiTestCase { @Test public void testControlUnlockedScreenOffAnimationDisabled_dozeAfterScreenOff() { - setShouldControlUnlockedScreenOffForTest(true); when(mFeatureFlags.isEnabled(Flags.LOCKSCREEN_ANIMATIONS)).thenReturn(false); assertFalse(mDozeParameters.shouldControlUnlockedScreenOff()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java index 8f3df09d913d..05fb1f5959ea 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java @@ -80,6 +80,7 @@ import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent; import com.android.keyguard.dagger.KeyguardStatusBarViewComponent; import com.android.keyguard.dagger.KeyguardStatusViewComponent; import com.android.keyguard.dagger.KeyguardUserSwitcherComponent; +import com.android.systemui.DejankUtils; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.biometrics.AuthController; @@ -331,6 +332,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { private NotificationListContainer mNotificationListContainer; @Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator; + @Mock + private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; private NotificationPanelViewController.PanelEventsEmitter mPanelEventsEmitter; private Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty(); private SysuiStatusBarStateController mStatusBarStateController; @@ -350,6 +353,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { mKeyguardStatusView = new KeyguardStatusView(mContext); mKeyguardStatusView.setId(R.id.keyguard_status_view); + DejankUtils.setImmediate(true); when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false); when(mHeadsUpCallback.getContext()).thenReturn(mContext); @@ -511,7 +515,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { mKeyguardUnlockAnimationController, mNotificationListContainer, mPanelEventsEmitter, - mNotificationStackSizeCalculator); + mNotificationStackSizeCalculator, + mUnlockedScreenOffAnimationController); mNotificationPanelViewController.initDependencies( mCentralSurfaces, () -> {}, @@ -939,6 +944,29 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { } @Test + public void testUnlockHintAnimation_runs_whenNotInPowerSaveMode_andDozeAmountIsZero() { + when(mPowerManager.isPowerSaveMode()).thenReturn(false); + when(mAmbientState.getDozeAmount()).thenReturn(0f); + mNotificationPanelViewController.startUnlockHintAnimation(); + assertThat(mNotificationPanelViewController.mHintAnimationRunning).isTrue(); + } + + @Test + public void testUnlockHintAnimation_doesNotRun_inPowerSaveMode() { + when(mPowerManager.isPowerSaveMode()).thenReturn(true); + mNotificationPanelViewController.startUnlockHintAnimation(); + assertThat(mNotificationPanelViewController.mHintAnimationRunning).isFalse(); + } + + @Test + public void testUnlockHintAnimation_doesNotRun_whenDozeAmountNotZero() { + when(mPowerManager.isPowerSaveMode()).thenReturn(false); + when(mAmbientState.getDozeAmount()).thenReturn(0.5f); + mNotificationPanelViewController.startUnlockHintAnimation(); + assertThat(mNotificationPanelViewController.mHintAnimationRunning).isFalse(); + } + + @Test public void setKeyguardStatusBarAlpha_setsAlphaOnKeyguardStatusBarController() { float statusBarAlpha = 0.5f; 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 509fa3b01b0a..ff2c05b04160 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 @@ -1238,23 +1238,23 @@ public class ScrimControllerTest extends SysuiTestCase { @Test public void expansionNotificationAlpha_shadeLocked_bouncerActive_usesBouncerInterpolator() { - when(mStatusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(true); + when(mStatusBarKeyguardViewManager.isBouncerInTransit()).thenReturn(true); mScrimController.transitionTo(ScrimState.SHADE_LOCKED); float expansion = 0.8f; float expectedAlpha = - BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(expansion); + BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion); assertAlphaAfterExpansion(mNotificationsScrim, expectedAlpha, expansion); expansion = 0.2f; - expectedAlpha = BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(expansion); + expectedAlpha = BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion); assertAlphaAfterExpansion(mNotificationsScrim, expectedAlpha, expansion); } @Test public void expansionNotificationAlpha_shadeLocked_bouncerNotActive_usesShadeInterpolator() { - when(mStatusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(false); + when(mStatusBarKeyguardViewManager.isBouncerInTransit()).thenReturn(false); mScrimController.transitionTo(ScrimState.SHADE_LOCKED); @@ -1269,7 +1269,7 @@ public class ScrimControllerTest extends SysuiTestCase { @Test public void notificationAlpha_unnocclusionAnimating_bouncerActive_usesKeyguardNotifAlpha() { - when(mStatusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(true); + when(mStatusBarKeyguardViewManager.isBouncerInTransit()).thenReturn(true); mScrimController.transitionTo(ScrimState.KEYGUARD); mScrimController.setUnocclusionAnimationRunning(true); @@ -1284,13 +1284,13 @@ public class ScrimControllerTest extends SysuiTestCase { // Verify normal behavior after mScrimController.setUnocclusionAnimationRunning(false); float expansion = 0.4f; - float alpha = 1 - BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(expansion); + float alpha = 1 - BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion); assertAlphaAfterExpansion(mNotificationsScrim, alpha, expansion); } @Test public void notificationAlpha_unnocclusionAnimating_bouncerNotActive_usesKeyguardNotifAlpha() { - when(mStatusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(false); + when(mStatusBarKeyguardViewManager.isBouncerInTransit()).thenReturn(false); mScrimController.transitionTo(ScrimState.KEYGUARD); mScrimController.setUnocclusionAnimationRunning(true); @@ -1311,26 +1311,26 @@ public class ScrimControllerTest extends SysuiTestCase { @Test public void notificationAlpha_inKeyguardState_bouncerActive_usesInvertedBouncerInterpolator() { - when(mStatusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(true); + when(mStatusBarKeyguardViewManager.isBouncerInTransit()).thenReturn(true); mScrimController.transitionTo(ScrimState.KEYGUARD); float expansion = 0.8f; - float alpha = 1 - BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(expansion); + float alpha = 1 - BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion); assertAlphaAfterExpansion(mNotificationsScrim, alpha, expansion); expansion = 0.4f; - alpha = 1 - BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(expansion); + alpha = 1 - BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion); assertAlphaAfterExpansion(mNotificationsScrim, alpha, expansion); expansion = 0.2f; - alpha = 1 - BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(expansion); + alpha = 1 - BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion); assertAlphaAfterExpansion(mNotificationsScrim, alpha, expansion); } @Test public void notificationAlpha_inKeyguardState_bouncerNotActive_usesInvertedShadeInterpolator() { - when(mStatusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(false); + when(mStatusBarKeyguardViewManager.isBouncerInTransit()).thenReturn(false); mScrimController.transitionTo(ScrimState.KEYGUARD); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java index 90cbf540004e..2b018727eb98 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java @@ -438,12 +438,12 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { } @Test - public void testBouncerIsInTransit() { + public void testIsBouncerInTransit() { when(mBouncer.inTransit()).thenReturn(true); - Truth.assertThat(mStatusBarKeyguardViewManager.bouncerIsInTransit()).isTrue(); + Truth.assertThat(mStatusBarKeyguardViewManager.isBouncerInTransit()).isTrue(); when(mBouncer.inTransit()).thenReturn(false); - Truth.assertThat(mStatusBarKeyguardViewManager.bouncerIsInTransit()).isFalse(); + Truth.assertThat(mStatusBarKeyguardViewManager.isBouncerInTransit()).isFalse(); mBouncer = null; - Truth.assertThat(mStatusBarKeyguardViewManager.bouncerIsInTransit()).isFalse(); + Truth.assertThat(mStatusBarKeyguardViewManager.isBouncerInTransit()).isFalse(); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt index 050563a5707c..0936b773d4b3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt @@ -31,6 +31,7 @@ import com.android.systemui.statusbar.LightRevealScrim import com.android.systemui.statusbar.StatusBarStateControllerImpl import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.settings.GlobalSettings +import junit.framework.Assert.assertFalse import org.junit.After import org.junit.Before import org.junit.Test @@ -133,7 +134,7 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { */ @Test fun testAodUiShownIfNotInteractive() { - `when`(dozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true) + `when`(dozeParameters.canControlUnlockedScreenOff()).thenReturn(true) `when`(powerManager.isInteractive).thenReturn(false) val callbackCaptor = ArgumentCaptor.forClass(Runnable::class.java) @@ -156,7 +157,7 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { */ @Test fun testAodUiNotShownIfInteractive() { - `when`(dozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true) + `when`(dozeParameters.canControlUnlockedScreenOff()).thenReturn(true) `when`(powerManager.isInteractive).thenReturn(true) val callbackCaptor = ArgumentCaptor.forClass(Runnable::class.java) @@ -167,4 +168,13 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() { verify(notificationPanelViewController, never()).showAodUi() } + + @Test + fun testNoAnimationPlaying_dozeParamsCanNotControlScreenOff() { + `when`(dozeParameters.canControlUnlockedScreenOff()).thenReturn(false) + + assertFalse(controller.shouldPlayUnlockedScreenOffAnimation()) + controller.startAnimation() + assertFalse(controller.isAnimationPlaying()) + } }
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt index f58403d3651a..b4f3987b2f95 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt @@ -26,13 +26,13 @@ import androidx.test.filters.SmallTest import com.android.internal.logging.UiEventLogger import com.android.systemui.R import com.android.systemui.SysuiTestCase -import com.android.systemui.keyguard.ScreenLifecycle import com.android.systemui.plugins.FalsingManager import com.android.systemui.qs.user.UserSwitchDialogController import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.phone.DozeParameters import com.android.systemui.statusbar.phone.LockscreenGestureLogger import com.android.systemui.statusbar.phone.ScreenOffAnimationController +import com.google.common.truth.Truth.assertThat import org.junit.After import org.junit.Before import org.junit.Test @@ -48,9 +48,6 @@ import org.mockito.MockitoAnnotations @RunWith(AndroidTestingRunner::class) class KeyguardQsUserSwitchControllerTest : SysuiTestCase() { @Mock - private lateinit var screenLifecycle: ScreenLifecycle - - @Mock private lateinit var userSwitcherController: UserSwitcherController @Mock @@ -93,7 +90,6 @@ class KeyguardQsUserSwitchControllerTest : SysuiTestCase() { view, context, context.resources, - screenLifecycle, userSwitcherController, keyguardStateController, falsingManager, @@ -108,6 +104,8 @@ class KeyguardQsUserSwitchControllerTest : SysuiTestCase() { testableLooper.processAllMessages() `when`(userSwitcherController.keyguardStateController).thenReturn(keyguardStateController) `when`(userSwitcherController.keyguardStateController.isShowing).thenReturn(true) + `when`(keyguardStateController.isShowing).thenReturn(true) + `when`(keyguardStateController.isKeyguardGoingAway).thenReturn(false) keyguardQsUserSwitchController.init() } @@ -122,4 +120,28 @@ class KeyguardQsUserSwitchControllerTest : SysuiTestCase() { verify(uiEventLogger, times(1)) .log(LockscreenGestureLogger.LockscreenUiEvent.LOCKSCREEN_SWITCH_USER_TAP) } + + @Test + fun testAvatarExistsWhenKeyguardGoingAway() { + `when`(keyguardStateController.isShowing).thenReturn(false) + `when`(keyguardStateController.isKeyguardGoingAway).thenReturn(true) + keyguardQsUserSwitchController.updateKeyguardShowing(true /* forceViewUpdate */) + assertThat(keyguardQsUserSwitchController.mUserAvatarView.isEmpty).isFalse() + } + + @Test + fun testAvatarExistsWhenKeyguardShown() { + `when`(keyguardStateController.isShowing).thenReturn(true) + `when`(keyguardStateController.isKeyguardGoingAway).thenReturn(false) + keyguardQsUserSwitchController.updateKeyguardShowing(true /* forceViewUpdate */) + assertThat(keyguardQsUserSwitchController.mUserAvatarView.isEmpty).isFalse() + } + + @Test + fun testAvatarGoneWhenKeyguardGone() { + `when`(keyguardStateController.isShowing).thenReturn(false) + `when`(keyguardStateController.isKeyguardGoingAway).thenReturn(false) + keyguardQsUserSwitchController.updateKeyguardShowing(true /* forceViewUpdate */) + assertThat(keyguardQsUserSwitchController.mUserAvatarView.isEmpty).isTrue() + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SafetyControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SafetyControllerTest.kt new file mode 100644 index 000000000000..89989ce81dd6 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SafetyControllerTest.kt @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.policy + +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.content.pm.PackageManager +import android.net.Uri +import android.os.Handler +import android.safetycenter.SafetyCenterManager +import android.testing.AndroidTestingRunner +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.util.mockito.any +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.ArgumentMatchers.eq +import org.mockito.ArgumentMatchers.same +import org.mockito.Mock +import org.mockito.MockitoAnnotations +import org.mockito.Mockito.never +import org.mockito.Mockito.reset +import org.mockito.Mockito.times +import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` + +@SmallTest +@RunWith(AndroidTestingRunner::class) +class SafetyControllerTest : SysuiTestCase() { + + private val TEST_PC_PKG = "testPermissionControllerPackageName" + private val OTHER_PKG = "otherPackageName" + + @Mock + private lateinit var context: Context + @Mock + private lateinit var scm: SafetyCenterManager + @Mock + private lateinit var pm: PackageManager + @Mock + private lateinit var handler: Handler + @Mock + private lateinit var listener: SafetyController.Listener + + private val packageDataScheme = "package" + + private lateinit var controller: SafetyController + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + `when`(pm.permissionControllerPackageName).thenReturn(TEST_PC_PKG) + `when`(scm.isSafetyCenterEnabled).thenReturn(false) + `when`(handler.post(any(Runnable::class.java))).thenAnswer { + (it.arguments[0] as Runnable).run() + true + } + + controller = SafetyController(context, pm, scm, handler) + } + + @Test + fun addingFirstListenerRegistersReceiver() { + `when`(scm.isSafetyCenterEnabled).thenReturn(true) + controller.addCallback(listener) + verify(listener, times(1)).onSafetyCenterEnableChanged(true) + val filter = ArgumentCaptor.forClass(IntentFilter::class.java) + verify(context, times(1)).registerReceiver( + same(controller.mPermControllerChangeReceiver), filter.capture()) + assertEquals(Intent.ACTION_PACKAGE_CHANGED, filter.value.getAction(0)) + assertEquals(packageDataScheme, filter.value.getDataScheme(0)) + } + + @Test + fun removingLastListenerDeregistersReceiver() { + controller.addCallback(listener) + controller.removeCallback(listener) + verify(context, times(1)).unregisterReceiver( + eq(controller.mPermControllerChangeReceiver)) + } + + @Test + fun listenersCalledWhenBroadcastReceivedWithPCPackageAndStateChange() { + `when`(scm.isSafetyCenterEnabled).thenReturn(false) + controller.addCallback(listener) + reset(listener) + `when`(scm.isSafetyCenterEnabled).thenReturn(true) + val testIntent = Intent(Intent.ACTION_PACKAGE_CHANGED) + testIntent.data = Uri.parse("package:$TEST_PC_PKG") + controller.mPermControllerChangeReceiver.onReceive(context, testIntent) + verify(listener, times(1)).onSafetyCenterEnableChanged(true) + } + + @Test + fun listenersNotCalledWhenBroadcastReceivedWithOtherPackage() { + `when`(scm.isSafetyCenterEnabled).thenReturn(true) + controller.addCallback(listener) + reset(listener) + val testIntent = Intent(Intent.ACTION_PACKAGE_CHANGED) + testIntent.data = Uri.parse("package:$OTHER_PKG") + controller.mPermControllerChangeReceiver.onReceive(context, testIntent) + verify(listener, never()).onSafetyCenterEnableChanged(true) + } + + @Test + fun listenersNotCalledWhenBroadcastReceivedWithNoStateChange() { + `when`(scm.isSafetyCenterEnabled).thenReturn(false) + controller.addCallback(listener) + reset(listener) + val testIntent = Intent(Intent.ACTION_PACKAGE_CHANGED) + testIntent.data = Uri.parse("package:$TEST_PC_PKG") + controller.mPermControllerChangeReceiver.onReceive(context, testIntent) + verify(listener, never()).onSafetyCenterEnableChanged(true) + } +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt index 799dafcd01b8..e3d2a2951c97 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt @@ -28,6 +28,7 @@ import android.hardware.fingerprint.FingerprintManager import android.os.Handler import android.os.UserHandle import android.os.UserManager +import android.provider.Settings import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.ThreadedRenderer @@ -51,6 +52,7 @@ import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.phone.NotificationShadeWindowView import com.android.systemui.telephony.TelephonyListenerManager import com.android.systemui.util.concurrency.FakeExecutor +import com.android.systemui.util.settings.GlobalSettings import com.android.systemui.util.settings.SecureSettings import com.android.systemui.util.time.FakeSystemClock import org.junit.Assert.assertEquals @@ -67,6 +69,7 @@ import org.mockito.Mockito.`when` import org.mockito.Mockito.any import org.mockito.Mockito.doNothing import org.mockito.Mockito.doReturn +import org.mockito.Mockito.eq import org.mockito.Mockito.mock import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @@ -95,6 +98,7 @@ class UserSwitcherControllerTest : SysuiTestCase() { @Mock private lateinit var notificationShadeWindowView: NotificationShadeWindowView @Mock private lateinit var threadedRenderer: ThreadedRenderer @Mock private lateinit var dialogLaunchAnimator: DialogLaunchAnimator + @Mock private lateinit var globalSettings: GlobalSettings private lateinit var testableLooper: TestableLooper private lateinit var bgExecutor: FakeExecutor private lateinit var longRunningExecutor: FakeExecutor @@ -148,6 +152,22 @@ class UserSwitcherControllerTest : SysuiTestCase() { `when`(userTracker.userId).thenReturn(ownerId) `when`(userTracker.userInfo).thenReturn(ownerInfo) + `when`( + globalSettings.getIntForUser( + eq(Settings.Global.ADD_USERS_WHEN_LOCKED), + anyInt(), + eq(UserHandle.USER_SYSTEM) + ) + ).thenReturn(0) + + `when`( + globalSettings.getIntForUser( + eq(Settings.Global.USER_SWITCHER_ENABLED), + anyInt(), + eq(UserHandle.USER_SYSTEM) + ) + ).thenReturn(1) + setupController() } @@ -168,6 +188,7 @@ class UserSwitcherControllerTest : SysuiTestCase() { falsingManager, telephonyListenerManager, secureSettings, + globalSettings, bgExecutor, longRunningExecutor, uiExecutor, @@ -469,4 +490,43 @@ class UserSwitcherControllerTest : SysuiTestCase() { // THEN a supervised user can NOT be constructed assertFalse(userSwitcherController.canCreateSupervisedUser()) } + + @Test + fun testCannotCreateUserWhenUserSwitcherDisabled() { + `when`( + globalSettings.getIntForUser( + eq(Settings.Global.USER_SWITCHER_ENABLED), + anyInt(), + eq(UserHandle.USER_SYSTEM) + ) + ).thenReturn(0) + setupController() + assertFalse(userSwitcherController.canCreateUser()) + } + + @Test + fun testCannotCreateGuestUserWhenUserSwitcherDisabled() { + `when`( + globalSettings.getIntForUser( + eq(Settings.Global.USER_SWITCHER_ENABLED), + anyInt(), + eq(UserHandle.USER_SYSTEM) + ) + ).thenReturn(0) + setupController() + assertFalse(userSwitcherController.canCreateGuest(false)) + } + + @Test + fun testCannotCreateSupervisedUserWhenUserSwitcherDisabled() { + `when`( + globalSettings.getIntForUser( + eq(Settings.Global.USER_SWITCHER_ENABLED), + anyInt(), + eq(UserHandle.USER_SYSTEM) + ) + ).thenReturn(0) + setupController() + assertFalse(userSwitcherController.canCreateSupervisedUser()) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayApplierTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayApplierTest.java index 2c461ae1b598..3032ff1fe61f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayApplierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayApplierTest.java @@ -104,7 +104,7 @@ public class ThemeOverlayApplierTest extends SysuiTestCase { public void setup() throws Exception { MockitoAnnotations.initMocks(this); mManager = new ThemeOverlayApplier(mOverlayManager, - MoreExecutors.directExecutor(), MoreExecutors.directExecutor(), + MoreExecutors.directExecutor(), LAUNCHER_PACKAGE, THEMEPICKER_PACKAGE, mDumpManager) { @Override protected OverlayManagerTransaction.Builder getTransactionBuilder() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt index 7ac243452222..05a8f0a35e28 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt @@ -78,6 +78,9 @@ class DeviceFoldStateProviderTest : SysuiTestCase() { @Before fun setUp() { MockitoAnnotations.initMocks(this) + overrideResource( + com.android.internal.R.integer.config_unfoldTransitionHalfFoldedTimeout, + HALF_OPENED_TIMEOUT_MILLIS.toInt()) deviceStates = FoldableTestUtils.findDeviceStates(context) foldStateProvider = @@ -319,4 +322,8 @@ class DeviceFoldStateProviderTest : SysuiTestCase() { private fun sendHingeAngleEvent(angle: Int) { hingeAngleCaptor.value.accept(angle.toFloat()) } + + companion object { + private const val HALF_OPENED_TIMEOUT_MILLIS = 300L + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt b/packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt index 3d554880ed58..b30c20db642d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt @@ -21,11 +21,16 @@ import android.hardware.usb.IUsbSerialReader import android.hardware.usb.UsbAccessory import android.hardware.usb.UsbManager import android.testing.AndroidTestingRunner +import android.testing.TestableLooper import android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS import androidx.test.filters.SmallTest import androidx.test.rule.ActivityTestRule +import androidx.test.runner.intercepting.SingleActivityFactory import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat + +import javax.inject.Inject + import org.junit.After import org.junit.Before import org.junit.Rule @@ -37,14 +42,26 @@ import org.junit.runner.RunWith */ @RunWith(AndroidTestingRunner::class) @SmallTest +@TestableLooper.RunWithLooper class UsbPermissionActivityTest : SysuiTestCase() { - class UsbPermissionActivityTestable : UsbPermissionActivity() + private var mMessage: UsbAudioWarningDialogMessage = UsbAudioWarningDialogMessage() + + open class UsbPermissionActivityTestable @Inject constructor ( + val message: UsbAudioWarningDialogMessage + ) + : UsbPermissionActivity(UsbAudioWarningDialogMessage()) @Rule @JvmField var activityRule = ActivityTestRule<UsbPermissionActivityTestable>( - UsbPermissionActivityTestable::class.java, false, false) + object : SingleActivityFactory<UsbPermissionActivityTestable>( + UsbPermissionActivityTestable::class.java + ) { + override fun create(intent: Intent?): UsbPermissionActivityTestable { + return UsbPermissionActivityTestable(mMessage) + } + }, false, false) private val activityIntent = Intent(mContext, UsbPermissionActivityTestable::class.java) .apply { @@ -72,6 +89,7 @@ class UsbPermissionActivityTest : SysuiTestCase() { @Before fun setUp() { + UsbPermissionActivityTestable(mMessage) activityRule.launchActivity(activityIntent) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakDetectorTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakDetectorTest.java index 3ee1a27dc69a..8f934335e93b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakDetectorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakDetectorTest.java @@ -52,6 +52,8 @@ public class LeakDetectorTest extends SysuiTestCase { private Object mObject; private Collection<?> mCollection; + + private CollectionWaiter trackObjectWith(Consumer<Object> tracker) { mObject = new Object(); CollectionWaiter collectionWaiter = ReferenceTestUtils.createCollectionWaiter(mObject); @@ -69,7 +71,9 @@ public class LeakDetectorTest extends SysuiTestCase { @Before public void setup() { - mLeakDetector = LeakDetector.create(Mockito.mock(DumpManager.class)); + TrackedCollections collections = new TrackedCollections(); + mLeakDetector = new LeakDetector(collections, new TrackedGarbage(collections), + new TrackedObjects(collections), Mockito.mock(DumpManager.class)); // Note: Do not try to factor out object / collection waiter creation. The optimizer will // try and cache accesses to fields and thus create a GC root for the duration of the test diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java index 01769e52c8d3..b1950eac9846 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java @@ -20,6 +20,7 @@ import static android.view.View.GONE; import static android.view.View.VISIBLE; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -323,6 +324,7 @@ public class WalletScreenControllerTest extends SysuiTestCase { assertEquals(GONE, mWalletView.getCardCarousel().getVisibility()); assertEquals(VISIBLE, mWalletView.getEmptyStateView().getVisibility()); assertEquals(GONE, mWalletView.getErrorView().getVisibility()); + assertTrue(mWalletView.getAppButton().hasOnClickListeners()); } @Test diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml index c340432b9b8c..67d405d1e01e 100644 --- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml +++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml @@ -44,6 +44,9 @@ --> <bool name="config_fillMainBuiltInDisplayCutout">true</bool> + <!-- Height of the status bar --> + <dimen name="status_bar_height_portrait">48dp</dimen> + <dimen name="status_bar_height_landscape">28dp</dimen> </resources> diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml index 928d9dfa3ce1..e08c32fc4d4b 100644 --- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml +++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml @@ -56,6 +56,9 @@ --> <bool name="config_fillMainBuiltInDisplayCutout">true</bool> + <!-- Height of the status bar --> + <dimen name="status_bar_height_portrait">48dp</dimen> + <dimen name="status_bar_height_landscape">28dp</dimen> </resources> diff --git a/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values/config.xml index 62f0535a1746..68916cc3494c 100644 --- a/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values/config.xml +++ b/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values/config.xml @@ -48,6 +48,9 @@ --> <bool name="config_fillMainBuiltInDisplayCutout">true</bool> + <!-- Height of the status bar --> + <dimen name="status_bar_height_portrait">136px</dimen> + <dimen name="status_bar_height_landscape">28dp</dimen> </resources> diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml index a9f8b4bc6329..605059b27f37 100644 --- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml +++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml @@ -47,6 +47,9 @@ --> <bool name="config_fillMainBuiltInDisplayCutout">true</bool> + <!-- Height of the status bar --> + <dimen name="status_bar_height_portrait">48dp</dimen> + <dimen name="status_bar_height_landscape">28dp</dimen> </resources> diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml index be7d0e48fa3f..370d73019669 100644 --- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml +++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml @@ -47,6 +47,9 @@ --> <bool name="config_fillMainBuiltInDisplayCutout">true</bool> + <!-- Height of the status bar --> + <dimen name="status_bar_height_portrait">48dp</dimen> + <dimen name="status_bar_height_landscape">28dp</dimen> </resources> diff --git a/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values/config.xml index cc51ebee270c..98779f0b3bc1 100644 --- a/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values/config.xml +++ b/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values/config.xml @@ -19,6 +19,12 @@ <string translatable="false" name="config_mainBuiltInDisplayCutout"></string> <string translatable="false" name="config_mainBuiltInDisplayCutoutRectApproximation"></string> + <!-- Height of the status bar in portrait. The height should be + Max((status bar content height + waterfall top size), top cutout size) --> + <dimen name="status_bar_height_portrait">28dp</dimen> + <!-- Max((28 + 20), 0) = 48 --> + <dimen name="status_bar_height_landscape">48dp</dimen> + <dimen name="waterfall_display_left_edge_size">20dp</dimen> <dimen name="waterfall_display_top_edge_size">0dp</dimen> <dimen name="waterfall_display_right_edge_size">20dp</dimen> diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml index 78cc7e04c7a0..176f1dc46b0c 100644 --- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml +++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml @@ -47,6 +47,9 @@ --> <bool name="config_fillMainBuiltInDisplayCutout">true</bool> + <!-- Height of the status bar --> + <dimen name="status_bar_height_portrait">48dp</dimen> + <dimen name="status_bar_height_landscape">28dp</dimen> </resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values/config.xml b/packages/overlays/NoCutoutOverlay/res/values/config.xml index 84b91b85350d..ed0340b11229 100644 --- a/packages/overlays/NoCutoutOverlay/res/values/config.xml +++ b/packages/overlays/NoCutoutOverlay/res/values/config.xml @@ -25,4 +25,7 @@ by shrinking the display such that it does not overlap the cutout area. --> <bool name="config_maskMainBuiltInDisplayCutout">true</bool> + <!-- Height of the status bar --> + <dimen name="status_bar_height_portrait">28dp</dimen> + <dimen name="status_bar_height_landscape">28dp</dimen> </resources> diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java index 5ef1008afad5..562d11a0b197 100644 --- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java +++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java @@ -69,6 +69,7 @@ import android.os.ServiceManager; import android.os.SystemClock; import android.os.Trace; import android.provider.Settings; +import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.view.Display; @@ -218,12 +219,6 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ @NonNull KeyEventDispatcher getKeyEventDispatcher(); /** - * @param windowId The id of the window of interest - * @return The magnification spec for the window, or {@code null} if none is available - */ - @Nullable MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId); - - /** * @param displayId The display id. * @return The current injector of motion events used on the display, if one exists. */ @@ -557,7 +552,8 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ final int resolvedWindowId; RemoteAccessibilityConnection connection; Region partialInteractiveRegion = Region.obtain(); - MagnificationSpec spec; + final MagnificationSpec spec; + final float[] transformMatrix; synchronized (mLock) { mUsesAccessibilityCache = true; if (!hasRightsToCurrentUserLocked()) { @@ -581,7 +577,10 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ partialInteractiveRegion.recycle(); partialInteractiveRegion = null; } - spec = mSystemSupport.getCompatibleMagnificationSpecLocked(resolvedWindowId); + final Pair<float[], MagnificationSpec> transformMatrixAndSpec = + getTransformMatrixAndSpecLocked(resolvedWindowId); + transformMatrix = transformMatrixAndSpec.first; + spec = transformMatrixAndSpec.second; } if (!mSecurityPolicy.checkAccessibilityAccess(this)) { return null; @@ -594,12 +593,12 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ logTraceIntConn("findAccessibilityNodeInfosByViewId", accessibilityNodeId + ";" + viewIdResName + ";" + partialInteractiveRegion + ";" + interactionId + ";" + callback + ";" + mFetchFlags + ";" + interrogatingPid - + ";" + interrogatingTid + ";" + spec); + + ";" + interrogatingTid + ";" + spec + ";" + Arrays.toString(transformMatrix)); } try { connection.getRemote().findAccessibilityNodeInfosByViewId(accessibilityNodeId, viewIdResName, partialInteractiveRegion, interactionId, callback, mFetchFlags, - interrogatingPid, interrogatingTid, spec); + interrogatingPid, interrogatingTid, spec, transformMatrix); return mSecurityPolicy.computeValidReportedPackages( connection.getPackageName(), connection.getUid()); } catch (RemoteException re) { @@ -630,7 +629,8 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ final int resolvedWindowId; RemoteAccessibilityConnection connection; Region partialInteractiveRegion = Region.obtain(); - MagnificationSpec spec; + final MagnificationSpec spec; + final float [] transformMatrix; synchronized (mLock) { mUsesAccessibilityCache = true; if (!hasRightsToCurrentUserLocked()) { @@ -654,7 +654,10 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ partialInteractiveRegion.recycle(); partialInteractiveRegion = null; } - spec = mSystemSupport.getCompatibleMagnificationSpecLocked(resolvedWindowId); + final Pair<float[], MagnificationSpec> transformMatrixAndSpec = + getTransformMatrixAndSpecLocked(resolvedWindowId); + transformMatrix = transformMatrixAndSpec.first; + spec = transformMatrixAndSpec.second; } if (!mSecurityPolicy.checkAccessibilityAccess(this)) { return null; @@ -667,12 +670,12 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ logTraceIntConn("findAccessibilityNodeInfosByText", accessibilityNodeId + ";" + text + ";" + partialInteractiveRegion + ";" + interactionId + ";" + callback + ";" + mFetchFlags + ";" + interrogatingPid - + ";" + interrogatingTid + ";" + spec); + + ";" + interrogatingTid + ";" + spec + ";" + Arrays.toString(transformMatrix)); } try { connection.getRemote().findAccessibilityNodeInfosByText(accessibilityNodeId, text, partialInteractiveRegion, interactionId, callback, mFetchFlags, - interrogatingPid, interrogatingTid, spec); + interrogatingPid, interrogatingTid, spec, transformMatrix); return mSecurityPolicy.computeValidReportedPackages( connection.getPackageName(), connection.getUid()); } catch (RemoteException re) { @@ -704,7 +707,8 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ final int resolvedWindowId; RemoteAccessibilityConnection connection; Region partialInteractiveRegion = Region.obtain(); - MagnificationSpec spec; + final MagnificationSpec spec; + final float[] transformMatrix; synchronized (mLock) { mUsesAccessibilityCache = true; if (!hasRightsToCurrentUserLocked()) { @@ -728,7 +732,10 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ partialInteractiveRegion.recycle(); partialInteractiveRegion = null; } - spec = mSystemSupport.getCompatibleMagnificationSpecLocked(resolvedWindowId); + final Pair<float[], MagnificationSpec> transformMatrixAndSpec = + getTransformMatrixAndSpecLocked(resolvedWindowId); + transformMatrix = transformMatrixAndSpec.first; + spec = transformMatrixAndSpec.second; } if (!mSecurityPolicy.checkAccessibilityAccess(this)) { return null; @@ -741,12 +748,14 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ logTraceIntConn("findAccessibilityNodeInfoByAccessibilityId", accessibilityNodeId + ";" + partialInteractiveRegion + ";" + interactionId + ";" + callback + ";" + (mFetchFlags | flags) + ";" + interrogatingPid + ";" - + interrogatingTid + ";" + spec + ";" + arguments); + + interrogatingTid + ";" + spec + ";" + Arrays.toString(transformMatrix) + + ";" + arguments); } try { connection.getRemote().findAccessibilityNodeInfoByAccessibilityId( accessibilityNodeId, partialInteractiveRegion, interactionId, callback, - mFetchFlags | flags, interrogatingPid, interrogatingTid, spec, arguments); + mFetchFlags | flags, interrogatingPid, interrogatingTid, spec, transformMatrix, + arguments); return mSecurityPolicy.computeValidReportedPackages( connection.getPackageName(), connection.getUid()); } catch (RemoteException re) { @@ -778,7 +787,8 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ final int resolvedWindowId; RemoteAccessibilityConnection connection; Region partialInteractiveRegion = Region.obtain(); - MagnificationSpec spec; + final MagnificationSpec spec; + final float[] transformMatrix; synchronized (mLock) { if (!hasRightsToCurrentUserLocked()) { return null; @@ -802,7 +812,10 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ partialInteractiveRegion.recycle(); partialInteractiveRegion = null; } - spec = mSystemSupport.getCompatibleMagnificationSpecLocked(resolvedWindowId); + final Pair<float[], MagnificationSpec> transformMatrixAndSpec = + getTransformMatrixAndSpecLocked(resolvedWindowId); + transformMatrix = transformMatrixAndSpec.first; + spec = transformMatrixAndSpec.second; } if (!mSecurityPolicy.checkAccessibilityAccess(this)) { return null; @@ -815,12 +828,13 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ logTraceIntConn("findFocus", accessibilityNodeId + ";" + focusType + ";" + partialInteractiveRegion + ";" + interactionId + ";" + callback + ";" + mFetchFlags + ";" + interrogatingPid - + ";" + interrogatingTid + ";" + spec); + + ";" + interrogatingTid + ";" + spec + ";" + + Arrays.toString(transformMatrix)); } try { connection.getRemote().findFocus(accessibilityNodeId, focusType, partialInteractiveRegion, interactionId, callback, mFetchFlags, - interrogatingPid, interrogatingTid, spec); + interrogatingPid, interrogatingTid, spec, transformMatrix); return mSecurityPolicy.computeValidReportedPackages( connection.getPackageName(), connection.getUid()); } catch (RemoteException re) { @@ -852,7 +866,8 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ final int resolvedWindowId; RemoteAccessibilityConnection connection; Region partialInteractiveRegion = Region.obtain(); - MagnificationSpec spec; + final MagnificationSpec spec; + final float[] transformMatrix; synchronized (mLock) { if (!hasRightsToCurrentUserLocked()) { return null; @@ -875,7 +890,11 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ partialInteractiveRegion.recycle(); partialInteractiveRegion = null; } - spec = mSystemSupport.getCompatibleMagnificationSpecLocked(resolvedWindowId); + + final Pair<float[], MagnificationSpec> transformMatrixAndSpec = + getTransformMatrixAndSpecLocked(resolvedWindowId); + transformMatrix = transformMatrixAndSpec.first; + spec = transformMatrixAndSpec.second; } if (!mSecurityPolicy.checkAccessibilityAccess(this)) { return null; @@ -888,12 +907,13 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ logTraceIntConn("focusSearch", accessibilityNodeId + ";" + direction + ";" + partialInteractiveRegion + ";" + interactionId + ";" + callback + ";" + mFetchFlags + ";" - + interrogatingPid + ";" + interrogatingTid + ";" + spec); + + interrogatingPid + ";" + interrogatingTid + ";" + spec + ";" + + Arrays.toString(transformMatrix)); } try { connection.getRemote().focusSearch(accessibilityNodeId, direction, partialInteractiveRegion, interactionId, callback, mFetchFlags, - interrogatingPid, interrogatingTid, spec); + interrogatingPid, interrogatingTid, spec, transformMatrix); return mSecurityPolicy.computeValidReportedPackages( connection.getPackageName(), connection.getUid()); } catch (RemoteException re) { @@ -1652,6 +1672,23 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ mInvocationHandler.startInputLocked(startInputToken, inputContext, editorInfo, restarting); } + + + @Nullable + Pair<float[], MagnificationSpec> getTransformMatrixAndSpecLocked(int resolvedWindowId) { + final WindowInfo windowInfo = + mA11yWindowManager.findWindowInfoByIdLocked(resolvedWindowId); + if (windowInfo == null) { + Slog.w(LOG_TAG, "getTransformMatrixAndSpec, windowInfo is null window id = " + + resolvedWindowId); + return new Pair<>(null, null); + } + + final MagnificationSpec spec = new MagnificationSpec(); + spec.setTo(windowInfo.mMagnificationSpec); + return new Pair<>(windowInfo.mTransformMatrix, spec); + } + /** * Called by the invocation handler to notify the service that the * state of magnification has changed. diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index e3226c7e2a7b..ac0c051794b3 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -106,6 +106,7 @@ import android.view.IWindow; import android.view.KeyEvent; import android.view.MagnificationSpec; import android.view.MotionEvent; +import android.view.WindowInfo; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityInteractionClient; @@ -3045,22 +3046,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub userState.setInteractiveUiTimeoutLocked(newInteractiveUiTimeout); } - @GuardedBy("mLock") - @Override - public MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId) { - IBinder windowToken = mA11yWindowManager.getWindowTokenForUserAndWindowIdLocked( - mCurrentUserId, windowId); - if (windowToken != null) { - if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MANAGER_INTERNAL)) { - mTraceManager.logTrace(LOG_TAG + ".getCompatibleMagnificationSpecForWindow", - FLAGS_WINDOW_MANAGER_INTERNAL, "windowToken=" + windowToken); - } - - return mWindowManagerService.getCompatibleMagnificationSpecForWindow(windowToken); - } - return null; - } - @Override public KeyEventDispatcher getKeyEventDispatcher() { if (mKeyEventDispatcher == null) { @@ -3741,7 +3726,14 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub boundsInScreenBeforeMagnification.centerY()); // Invert magnification if needed. - MagnificationSpec spec = getCompatibleMagnificationSpecLocked(focus.getWindowId()); + final WindowInfo windowInfo = mA11yWindowManager.findWindowInfoByIdLocked( + focus.getWindowId()); + MagnificationSpec spec = null; + if (windowInfo != null) { + spec = new MagnificationSpec(); + spec.setTo(windowInfo.mMagnificationSpec); + } + if (spec != null && !spec.isNop()) { boundsInScreenBeforeMagnification.offset((int) -spec.offsetX, (int) -spec.offsetY); diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java index aba32ec465b5..e30639cf416a 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java @@ -52,6 +52,7 @@ import com.android.server.wm.WindowManagerInternal; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -478,6 +479,9 @@ public class AccessibilityWindowManager { if (oldWindow.taskId != newWindow.taskId) { return true; } + if (!Arrays.equals(oldWindow.mTransformMatrix, newWindow.mTransformMatrix)) { + return true; + } return false; } @@ -800,14 +804,24 @@ public class AccessibilityWindowManager { pw.append(','); pw.println(); } - pw.append("Window["); + pw.append("A11yWindow["); AccessibilityWindowInfo window = mWindows.get(j); pw.append(window.toString()); pw.append(']'); + pw.println(); + final WindowInfo windowInfo = findWindowInfoByIdLocked(window.getId()); + if (windowInfo != null) { + pw.append("WindowInfo["); + pw.append(windowInfo.toString()); + pw.append("]"); + pw.println(); + } + } pw.println(); } } + } /** * Interface to send {@link AccessibilityEvent}. diff --git a/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java b/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java index 6828dd916701..6958b667da37 100644 --- a/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java +++ b/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java @@ -83,7 +83,7 @@ public class ActionReplacingCallback extends IAccessibilityInteractionConnection mConnectionWithReplacementActions.findAccessibilityNodeInfoByAccessibilityId( AccessibilityNodeInfo.ROOT_NODE_ID, null, mNodeWithReplacementActionsInteractionId, this, 0, - interrogatingPid, interrogatingTid, null, null); + interrogatingPid, interrogatingTid, null, null, null); } catch (RemoteException re) { if (DEBUG) { Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()"); diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java index ecc45eb743c6..6cfbfb8888fb 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java @@ -356,13 +356,6 @@ public class FullScreenMagnificationController implements mSpecAnimationBridge, spec, animationCallback); mControllerCtx.getHandler().sendMessage(m); } - - final boolean lastMagnificationActivated = mMagnificationActivated; - mMagnificationActivated = spec.scale > 1.0f; - if (mMagnificationActivated != lastMagnificationActivated) { - mMagnificationInfoChangedCallback.onFullScreenMagnificationActivationState( - mDisplayId, mMagnificationActivated); - } } /** @@ -376,9 +369,17 @@ public class FullScreenMagnificationController implements @GuardedBy("mLock") void onMagnificationChangedLocked() { + final float scale = getScale(); + final boolean lastMagnificationActivated = mMagnificationActivated; + mMagnificationActivated = scale > 1.0f; + if (mMagnificationActivated != lastMagnificationActivated) { + mMagnificationInfoChangedCallback.onFullScreenMagnificationActivationState( + mDisplayId, mMagnificationActivated); + } + final MagnificationConfig config = new MagnificationConfig.Builder() .setMode(MAGNIFICATION_MODE_FULLSCREEN) - .setScale(getScale()) + .setScale(scale) .setCenterX(getCenterX()) .setCenterY(getCenterY()).build(); mMagnificationInfoChangedCallback.onFullScreenMagnificationChanged(mDisplayId, diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java index b263fb377e82..bb286e61815d 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java @@ -16,6 +16,7 @@ package com.android.server.accessibility.magnification; +import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MODE_FULLSCREEN; import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MODE_WINDOW; import static android.content.pm.PackageManager.FEATURE_WINDOW_MAGNIFICATION; import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL; @@ -111,6 +112,15 @@ public class MagnificationController implements WindowMagnificationManager.Callb @GuardedBy("mLock") private final SparseLongArray mFullScreenModeEnabledTimeArray = new SparseLongArray(); + /** + * The transitioning magnification modes on the displays. The controller notifies + * magnification change depending on the target config mode. + * If the target mode is null, it means the config mode of the display is not + * transitioning. + */ + @GuardedBy("mLock") + private final SparseArray<Integer> mTransitionModes = new SparseArray(); + @GuardedBy("mLock") private final SparseArray<WindowManagerInternal.AccessibilityControllerInternal .UiChangesForAccessibilityCallbacks> mAccessibilityCallbacksDelegateArray = @@ -213,6 +223,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb final PointF currentCenter = getCurrentMagnificationCenterLocked(displayId, targetMode); final DisableMagnificationCallback animationCallback = getDisableMagnificationEndRunnableLocked(displayId); + if (currentCenter == null && animationCallback == null) { transitionCallBack.onResult(displayId, true); return; @@ -233,6 +244,9 @@ public class MagnificationController implements WindowMagnificationManager.Callb transitionCallBack.onResult(displayId, true); return; } + + setTransitionState(displayId, targetMode); + final FullScreenMagnificationController screenMagnificationController = getFullScreenMagnificationController(); final WindowMagnificationManager windowMagnificationMgr = getWindowMagnificationMgr(); @@ -286,26 +300,51 @@ public class MagnificationController implements WindowMagnificationManager.Callb Slog.w(TAG, "Discard previous animation request"); animationCallback.setExpiredAndRemoveFromListLocked(); } - final FullScreenMagnificationController screenMagnificationController = getFullScreenMagnificationController(); final WindowMagnificationManager windowMagnificationMgr = getWindowMagnificationMgr(); final float targetScale = Float.isNaN(config.getScale()) ? getTargetModeScaleFromCurrentMagnification(displayId, targetMode) : config.getScale(); - if (targetMode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) { - screenMagnificationController.reset(displayId, false); - windowMagnificationMgr.enableWindowMagnification(displayId, - targetScale, magnificationCenter.x, magnificationCenter.y, - animate ? STUB_ANIMATION_CALLBACK : null, id); - } else if (targetMode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) { - windowMagnificationMgr.disableWindowMagnification(displayId, false, null); - if (!screenMagnificationController.isRegistered(displayId)) { - screenMagnificationController.register(displayId); + try { + setTransitionState(displayId, targetMode); + + if (targetMode == MAGNIFICATION_MODE_WINDOW) { + screenMagnificationController.reset(displayId, false); + windowMagnificationMgr.enableWindowMagnification(displayId, + targetScale, magnificationCenter.x, magnificationCenter.y, + animate ? STUB_ANIMATION_CALLBACK : null, id); + } else if (targetMode == MAGNIFICATION_MODE_FULLSCREEN) { + windowMagnificationMgr.disableWindowMagnification(displayId, false, null); + if (!screenMagnificationController.isRegistered(displayId)) { + screenMagnificationController.register(displayId); + } + screenMagnificationController.setScaleAndCenter(displayId, targetScale, + magnificationCenter.x, magnificationCenter.y, animate, + id); } - screenMagnificationController.setScaleAndCenter(displayId, targetScale, - magnificationCenter.x, magnificationCenter.y, animate, - id); + } finally { + // Reset transition state after enabling target mode. + setTransitionState(displayId, null); + } + } + } + + /** + * Sets magnification config mode transition state. Called when the mode transition starts and + * ends. If the targetMode and the display id are null, it resets all + * the transition state. + * + * @param displayId The logical display id + * @param targetMode The transition target mode. It is not transitioning, if the target mode + * is set null + */ + private void setTransitionState(Integer displayId, Integer targetMode) { + synchronized (mLock) { + if (targetMode == null && displayId == null) { + mTransitionModes.clear(); + } else { + mTransitionModes.put(displayId, targetMode); } } } @@ -413,18 +452,57 @@ public class MagnificationController implements WindowMagnificationManager.Callb @Override public void onSourceBoundsChanged(int displayId, Rect bounds) { - final MagnificationConfig config = new MagnificationConfig.Builder() - .setMode(MAGNIFICATION_MODE_WINDOW) - .setScale(getWindowMagnificationMgr().getScale(displayId)) - .setCenterX(bounds.exactCenterX()) - .setCenterY(bounds.exactCenterY()).build(); - mAms.notifyMagnificationChanged(displayId, new Region(bounds), config); + if (shouldNotifyMagnificationChange(displayId, MAGNIFICATION_MODE_WINDOW)) { + final MagnificationConfig config = new MagnificationConfig.Builder() + .setMode(MAGNIFICATION_MODE_WINDOW) + .setScale(getWindowMagnificationMgr().getScale(displayId)) + .setCenterX(bounds.exactCenterX()) + .setCenterY(bounds.exactCenterY()).build(); + mAms.notifyMagnificationChanged(displayId, new Region(bounds), config); + } } @Override public void onFullScreenMagnificationChanged(int displayId, @NonNull Region region, @NonNull MagnificationConfig config) { - mAms.notifyMagnificationChanged(displayId, region, config); + if (shouldNotifyMagnificationChange(displayId, MAGNIFICATION_MODE_FULLSCREEN)) { + mAms.notifyMagnificationChanged(displayId, region, config); + } + } + + /** + * Should notify magnification change for the given display under the conditions below + * + * <ol> + * <li> 1. No mode transitioning and the change mode is active. </li> + * <li> 2. No mode transitioning and all the modes are inactive. </li> + * <li> 3. It is mode transitioning and the change mode is the transition mode. </li> + * </ol> + * + * @param displayId The logical display id + * @param changeMode The mode that has magnification spec change + */ + private boolean shouldNotifyMagnificationChange(int displayId, int changeMode) { + synchronized (mLock) { + final boolean fullScreenMagnifying = mFullScreenMagnificationController != null + && mFullScreenMagnificationController.isMagnifying(displayId); + final boolean windowEnabled = mWindowMagnificationMgr != null + && mWindowMagnificationMgr.isWindowMagnifierEnabled(displayId); + final Integer transitionMode = mTransitionModes.get(displayId); + if (((changeMode == MAGNIFICATION_MODE_FULLSCREEN && fullScreenMagnifying) + || (changeMode == MAGNIFICATION_MODE_WINDOW && windowEnabled)) + && (transitionMode == null)) { + return true; + } + if ((!fullScreenMagnifying && !windowEnabled) + && (transitionMode == null)) { + return true; + } + if (transitionMode != null && changeMode == transitionMode) { + return true; + } + } + return false; } private void disableFullScreenMagnificationIfNeeded(int displayId) { @@ -740,9 +818,32 @@ public class MagnificationController implements WindowMagnificationManager.Callb return; } setExpiredAndRemoveFromListLocked(); + setTransitionState(mDisplayId, null); + if (success) { adjustCurrentCenterIfNeededLocked(); applyMagnificationModeLocked(mTargetMode); + } else { + // Notify magnification change if magnification is inactive when the + // transition is failed. This is for the failed transition from + // full-screen to window mode. Disable magnification callback helps to send + // magnification inactive change since FullScreenMagnificationController + // would not notify magnification change if the spec is not changed. + final FullScreenMagnificationController screenMagnificationController = + getFullScreenMagnificationController(); + if (mCurrentMode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN + && !screenMagnificationController.isMagnifying(mDisplayId)) { + MagnificationConfig.Builder configBuilder = + new MagnificationConfig.Builder(); + Region region = new Region(); + configBuilder.setMode(MAGNIFICATION_MODE_FULLSCREEN) + .setScale(screenMagnificationController.getScale(mDisplayId)) + .setCenterX(screenMagnificationController.getCenterX(mDisplayId)) + .setCenterY(screenMagnificationController.getCenterY(mDisplayId)); + screenMagnificationController.getMagnificationRegion(mDisplayId, + region); + mAms.notifyMagnificationChanged(mDisplayId, region, configBuilder.build()); + } } updateMagnificationButton(mDisplayId, mTargetMode); if (mTransitionCallBack != null) { @@ -770,6 +871,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb return; } setExpiredAndRemoveFromListLocked(); + setTransitionState(mDisplayId, null); applyMagnificationModeLocked(mCurrentMode); updateMagnificationButton(mDisplayId, mCurrentMode); if (mTransitionCallBack != null) { diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index d7554cc42749..5acae4859ee8 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java @@ -20,9 +20,11 @@ import static android.content.Context.KEYGUARD_SERVICE; import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.res.Resources.ID_NULL; +import static android.provider.DeviceConfig.NAMESPACE_SYSTEMUI; import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME; +import android.annotation.NonNull; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityManagerInternal; @@ -83,6 +85,7 @@ import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; +import android.provider.DeviceConfig; import android.service.appwidget.AppWidgetServiceDumpProto; import android.service.appwidget.WidgetProto; import android.text.TextUtils; @@ -113,6 +116,7 @@ import com.android.internal.app.SuspendedAppActivity; import com.android.internal.app.UnlaunchableAppActivity; import com.android.internal.appwidget.IAppWidgetHost; import com.android.internal.appwidget.IAppWidgetService; +import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.internal.os.BackgroundThread; import com.android.internal.os.SomeArgs; import com.android.internal.util.ArrayUtils; @@ -150,6 +154,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku private static final String TAG = "AppWidgetServiceImpl"; private static final boolean DEBUG = false; + static final boolean DEBUG_PROVIDER_INFO_CACHE = true; private static final String OLD_KEYGUARD_HOST_PACKAGE = "android"; private static final String NEW_KEYGUARD_HOST_PACKAGE = "com.android.keyguard"; @@ -246,6 +251,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku private boolean mSafeMode; private int mMaxWidgetBitmapMemory; + private boolean mIsProviderInfoPersisted; AppWidgetServiceImpl(Context context) { mContext = context; @@ -263,6 +269,12 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku mCallbackHandler = new CallbackHandler(mContext.getMainLooper()); mBackupRestoreController = new BackupRestoreController(); mSecurityPolicy = new SecurityPolicy(); + mIsProviderInfoPersisted = !ActivityManager.isLowRamDeviceStatic() + && DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI, + SystemUiDeviceConfigFlags.PERSISTS_WIDGET_PROVIDER_INFO, true); + if (DEBUG_PROVIDER_INFO_CACHE && !mIsProviderInfoPersisted) { + Slog.d(TAG, "App widget provider info will not be persisted on this device"); + } computeMaximumWidgetBitmapMemory(); registerBroadcastReceiver(); @@ -607,10 +619,12 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } } + @GuardedBy("mLock") private void ensureGroupStateLoadedLocked(int userId) { ensureGroupStateLoadedLocked(userId, /* enforceUserUnlockingOrUnlocked */ true ); } + @GuardedBy("mLock") private void ensureGroupStateLoadedLocked(int userId, boolean enforceUserUnlockingOrUnlocked) { if (enforceUserUnlockingOrUnlocked && !isUserRunningAndUnlocked(userId)) { throw new IllegalStateException( @@ -1987,6 +2001,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } } + @GuardedBy("mLock") private void scheduleNotifyProviderChangedLocked(Widget widget) { long requestId = UPDATE_COUNTER.incrementAndGet(); if (widget != null) { @@ -2184,6 +2199,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } } + @GuardedBy("mLock") private void loadGroupWidgetProvidersLocked(int[] profileIds) { List<ResolveInfo> allReceivers = null; Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); @@ -2315,6 +2331,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku sendBroadcastAsUser(intent, widget.provider.id.getProfile()); } + @GuardedBy("mLock") private void registerForBroadcastsLocked(Provider provider, int[] appWidgetIds) { AppWidgetProviderInfo info = provider.getInfoLocked(mContext); if (info.updatePeriodMillis > 0) { @@ -2409,7 +2426,24 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } } - private static void serializeProvider(TypedXmlSerializer out, Provider p) throws IOException { + private static void serializeProvider( + @NonNull final TypedXmlSerializer out, @NonNull final Provider p) throws IOException { + Objects.requireNonNull(out); + Objects.requireNonNull(p); + serializeProviderInner(out, p, false /* persistsProviderInfo */); + } + + private static void serializeProviderWithProviderInfo( + @NonNull final TypedXmlSerializer out, @NonNull final Provider p) throws IOException { + Objects.requireNonNull(out); + Objects.requireNonNull(p); + serializeProviderInner(out, p, true /* persistsProviderInfo */); + } + + private static void serializeProviderInner(@NonNull final TypedXmlSerializer out, + @NonNull final Provider p, final boolean persistsProviderInfo) throws IOException { + Objects.requireNonNull(out); + Objects.requireNonNull(p); out.startTag(null, "p"); out.attribute(null, "pkg", p.id.componentName.getPackageName()); out.attribute(null, "cl", p.id.componentName.getClassName()); @@ -2417,6 +2451,12 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku if (!TextUtils.isEmpty(p.infoTag)) { out.attribute(null, "info_tag", p.infoTag); } + if (DEBUG_PROVIDER_INFO_CACHE && persistsProviderInfo && !p.mInfoParsed) { + Slog.d(TAG, "Provider info from " + p.id.componentName + " won't be persisted."); + } + if (persistsProviderInfo && p.mInfoParsed) { + AppWidgetXmlUtil.writeAppWidgetProviderInfoLocked(out, p.info); + } out.endTag(null, "p"); } @@ -2768,6 +2808,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } // only call from initialization -- it assumes that the data structures are all empty + @GuardedBy("mLock") private void loadGroupStateLocked(int[] profileIds) { // We can bind the widgets to host and providers only after // reading the host and providers for all users since a widget @@ -2959,6 +3000,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku return false; } + @GuardedBy("mLock") private void saveStateLocked(int userId) { tagProvidersAndHosts(); @@ -3012,6 +3054,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } } + @GuardedBy("mLock") private boolean writeProfileStateToFileLocked(FileOutputStream stream, int userId) { int N; @@ -3028,7 +3071,9 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku if (provider.getUserId() != userId) { continue; } - if (provider.shouldBePersisted()) { + if (mIsProviderInfoPersisted) { + serializeProviderWithProviderInfo(out, provider); + } else if (provider.shouldBePersisted()) { serializeProvider(out, provider); } } @@ -3074,6 +3119,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } } + @GuardedBy("mLock") private int readProfileStateFromFileLocked(FileInputStream stream, int userId, List<LoadedWidgetState> outLoadedWidgets) { int version = -1; @@ -3127,6 +3173,18 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku provider.zombie = true; provider.id = providerId; mProviders.add(provider); + } else if (mIsProviderInfoPersisted) { + final AppWidgetProviderInfo info = + AppWidgetXmlUtil.readAppWidgetProviderInfoLocked(parser); + if (DEBUG_PROVIDER_INFO_CACHE && info == null) { + Slog.d(TAG, "Unable to load widget provider info from xml for " + + providerId.componentName); + } + if (info != null) { + info.provider = providerId.componentName; + info.providerInfo = providerInfo; + provider.setInfoLocked(info); + } } final int providerTag = parser.getAttributeIntHex(null, "tag", @@ -3377,6 +3435,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku * * @return whether any providers were updated */ + @GuardedBy("mLock") private boolean updateProvidersForPackageLocked(String packageName, int userId, Set<ProviderId> removedProviders) { boolean providersUpdated = false; @@ -4162,6 +4221,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku /** * Adds all pending updates in {@param outUpdates} keys by the update time. */ + @GuardedBy("mLock") public void getPendingUpdatesForIdLocked(Context context, int appWidgetId, LongSparseArray<PendingHostUpdate> outUpdates) { long updateSequenceNo = lastWidgetUpdateSequenceNo; diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java new file mode 100644 index 000000000000..6a5dcc8c5945 --- /dev/null +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.appwidget; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.appwidget.AppWidgetProviderInfo; +import android.content.ComponentName; +import android.os.Build; +import android.text.TextUtils; +import android.util.Slog; +import android.util.TypedXmlPullParser; +import android.util.TypedXmlSerializer; + +import java.io.IOException; +import java.util.Objects; + +/** + * @hide + */ +public class AppWidgetXmlUtil { + + private static final String TAG = "AppWidgetXmlUtil"; + + private static final String ATTR_MIN_WIDTH = "min_width"; + private static final String ATTR_MIN_HEIGHT = "min_height"; + private static final String ATTR_MIN_RESIZE_WIDTH = "min_resize_width"; + private static final String ATTR_MIN_RESIZE_HEIGHT = "min_resize_height"; + private static final String ATTR_MAX_RESIZE_WIDTH = "max_resize_width"; + private static final String ATTR_MAX_RESIZE_HEIGHT = "max_resize_height"; + private static final String ATTR_TARGET_CELL_WIDTH = "target_cell_width"; + private static final String ATTR_TARGET_CELL_HEIGHT = "target_cell_height"; + private static final String ATTR_UPDATE_PERIOD_MILLIS = "update_period_millis"; + private static final String ATTR_INITIAL_LAYOUT = "initial_layout"; + private static final String ATTR_INITIAL_KEYGUARD_LAYOUT = "initial_keyguard_layout"; + private static final String ATTR_CONFIGURE = "configure"; + private static final String ATTR_LABEL = "label"; + private static final String ATTR_ICON = "icon"; + private static final String ATTR_PREVIEW_IMAGE = "preview_image"; + private static final String ATTR_PREVIEW_LAYOUT = "preview_layout"; + private static final String ATTR_AUTO_ADVANCED_VIEW_ID = "auto_advance_view_id"; + private static final String ATTR_RESIZE_MODE = "resize_mode"; + private static final String ATTR_WIDGET_CATEGORY = "widget_category"; + private static final String ATTR_WIDGET_FEATURES = "widget_features"; + private static final String ATTR_DESCRIPTION_RES = "description_res"; + private static final String ATTR_OS_FINGERPRINT = "os_fingerprint"; + + /** + * @hide + */ + public static void writeAppWidgetProviderInfoLocked(@NonNull final TypedXmlSerializer out, + @NonNull final AppWidgetProviderInfo info) throws IOException { + Objects.requireNonNull(out); + Objects.requireNonNull(info); + out.attributeInt(null, ATTR_MIN_WIDTH, info.minWidth); + out.attributeInt(null, ATTR_MIN_HEIGHT, info.minHeight); + out.attributeInt(null, ATTR_MIN_RESIZE_WIDTH, info.minResizeWidth); + out.attributeInt(null, ATTR_MIN_RESIZE_HEIGHT, info.minResizeHeight); + out.attributeInt(null, ATTR_MAX_RESIZE_WIDTH, info.maxResizeWidth); + out.attributeInt(null, ATTR_MAX_RESIZE_HEIGHT, info.maxResizeHeight); + out.attributeInt(null, ATTR_TARGET_CELL_WIDTH, info.targetCellWidth); + out.attributeInt(null, ATTR_TARGET_CELL_HEIGHT, info.targetCellHeight); + out.attributeInt(null, ATTR_UPDATE_PERIOD_MILLIS, info.updatePeriodMillis); + out.attributeInt(null, ATTR_INITIAL_LAYOUT, info.initialLayout); + out.attributeInt(null, ATTR_INITIAL_KEYGUARD_LAYOUT, info.initialKeyguardLayout); + if (info.configure != null) { + out.attribute(null, ATTR_CONFIGURE, info.configure.flattenToShortString()); + } + if (info.label != null) { + out.attribute(null, ATTR_LABEL, info.label); + } else if (AppWidgetServiceImpl.DEBUG_PROVIDER_INFO_CACHE) { + Slog.e(TAG, "Label is empty in " + info.provider); + } + out.attributeInt(null, ATTR_ICON, info.icon); + out.attributeInt(null, ATTR_PREVIEW_IMAGE, info.previewImage); + out.attributeInt(null, ATTR_PREVIEW_LAYOUT, info.previewLayout); + out.attributeInt(null, ATTR_AUTO_ADVANCED_VIEW_ID, info.autoAdvanceViewId); + out.attributeInt(null, ATTR_RESIZE_MODE, info.resizeMode); + out.attributeInt(null, ATTR_WIDGET_CATEGORY, info.widgetCategory); + out.attributeInt(null, ATTR_WIDGET_FEATURES, info.widgetFeatures); + out.attributeInt(null, ATTR_DESCRIPTION_RES, info.descriptionRes); + out.attribute(null, ATTR_OS_FINGERPRINT, Build.FINGERPRINT); + } + + /** + * @hide + */ + @Nullable + public static AppWidgetProviderInfo readAppWidgetProviderInfoLocked( + @NonNull final TypedXmlPullParser parser) { + Objects.requireNonNull(parser); + final String fingerprint = parser.getAttributeValue(null, ATTR_OS_FINGERPRINT); + if (!Build.FINGERPRINT.equals(fingerprint)) { + return null; + } + final AppWidgetProviderInfo info = new AppWidgetProviderInfo(); + info.minWidth = parser.getAttributeInt(null, ATTR_MIN_WIDTH, 0); + info.minHeight = parser.getAttributeInt(null, ATTR_MIN_HEIGHT, 0); + info.minResizeWidth = parser.getAttributeInt(null, ATTR_MIN_RESIZE_WIDTH, 0); + info.minResizeWidth = parser.getAttributeInt(null, ATTR_MIN_RESIZE_HEIGHT, 0); + info.maxResizeWidth = parser.getAttributeInt(null, ATTR_MAX_RESIZE_WIDTH, 0); + info.maxResizeHeight = parser.getAttributeInt(null, ATTR_MAX_RESIZE_HEIGHT, 0); + info.targetCellWidth = parser.getAttributeInt(null, ATTR_TARGET_CELL_WIDTH, 0); + info.targetCellHeight = parser.getAttributeInt(null, ATTR_TARGET_CELL_HEIGHT, 0); + info.updatePeriodMillis = parser.getAttributeInt(null, ATTR_UPDATE_PERIOD_MILLIS, 0); + info.initialLayout = parser.getAttributeInt(null, ATTR_INITIAL_LAYOUT, 0); + info.initialKeyguardLayout = parser.getAttributeInt( + null, ATTR_INITIAL_KEYGUARD_LAYOUT, 0); + final String configure = parser.getAttributeValue(null, ATTR_CONFIGURE); + if (!TextUtils.isEmpty(configure)) { + info.configure = ComponentName.unflattenFromString(configure); + } + info.label = parser.getAttributeValue(null, ATTR_LABEL); + info.icon = parser.getAttributeInt(null, ATTR_ICON, 0); + info.previewImage = parser.getAttributeInt(null, ATTR_PREVIEW_IMAGE, 0); + info.previewLayout = parser.getAttributeInt(null, ATTR_PREVIEW_LAYOUT, 0); + info.autoAdvanceViewId = parser.getAttributeInt(null, ATTR_AUTO_ADVANCED_VIEW_ID, 0); + info.resizeMode = parser.getAttributeInt(null, ATTR_RESIZE_MODE, 0); + info.widgetCategory = parser.getAttributeInt(null, ATTR_WIDGET_CATEGORY, 0); + info.widgetFeatures = parser.getAttributeInt(null, ATTR_WIDGET_FEATURES, 0); + info.descriptionRes = parser.getAttributeInt(null, ATTR_DESCRIPTION_RES, 0); + return info; + } +} diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java index ac0944be9739..b4c107c1a2c1 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java @@ -671,6 +671,9 @@ public class CompanionDeviceManagerService extends SystemService { association = AssociationInfo.builder(association) .setNotifyOnDeviceNearby(active) .build(); + // Do not need to call {@link BleCompanionDeviceScanner#restartScan()} since it will + // trigger {@link BleCompanionDeviceScanner#restartScan(int, AssociationInfo)} when + // an application sets/unsets the mNotifyOnDeviceNearby flag. mAssociationStore.updateAssociation(association); // TODO(b/218615198): correctly handle the case when the device is currently present. diff --git a/services/companion/java/com/android/server/companion/presence/BleCompanionDeviceScanner.java b/services/companion/java/com/android/server/companion/presence/BleCompanionDeviceScanner.java index 33301b180619..ad09f7cd3dde 100644 --- a/services/companion/java/com/android/server/companion/presence/BleCompanionDeviceScanner.java +++ b/services/companion/java/com/android/server/companion/presence/BleCompanionDeviceScanner.java @@ -194,6 +194,8 @@ class BleCompanionDeviceScanner implements AssociationStore.OnChangeListener { // Collect MAC addresses from all associations. final Set<String> macAddresses = new HashSet<>(); for (AssociationInfo association : mAssociationStore.getAssociations()) { + if (!association.isNotifyOnDeviceNearby()) continue; + // Beware that BT stack does not consider low-case MAC addresses valid, while // MacAddress.toString() return a low-case String. final String macAddress = association.getDeviceMacAddressAsString(); diff --git a/services/companion/java/com/android/server/companion/virtual/CameraAccessController.java b/services/companion/java/com/android/server/companion/virtual/CameraAccessController.java index adc8459de658..ec0da490adcf 100644 --- a/services/companion/java/com/android/server/companion/virtual/CameraAccessController.java +++ b/services/companion/java/com/android/server/companion/virtual/CameraAccessController.java @@ -30,6 +30,8 @@ import android.util.Slog; import com.android.internal.annotations.GuardedBy; +import java.util.Set; + /** * Handles blocking access to the camera for apps running on virtual devices. */ @@ -50,11 +52,23 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen @GuardedBy("mLock") private ArrayMap<String, InjectionSessionData> mPackageToSessionData = new ArrayMap<>(); + /** + * Mapping from camera ID to open camera app associations. Key is the camera id, value is the + * information of the app's uid and package name. + */ + @GuardedBy("mLock") + private ArrayMap<String, OpenCameraInfo> mAppsToBlockOnVirtualDevice = new ArrayMap<>(); + static class InjectionSessionData { public int appUid; public ArrayMap<String, CameraInjectionSession> cameraIdToSession = new ArrayMap<>(); } + static class OpenCameraInfo { + public String packageName; + public int packageUid; + } + interface CameraAccessBlockedCallback { /** * Called whenever an app was blocked from accessing a camera. @@ -98,6 +112,33 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen } } + /** + * Need to block camera access for applications running on virtual displays. + * <p> + * Apps that open the camera on the main display will need to block camera access if moved to a + * virtual display. + * + * @param runningUids uids of the application running on the virtual display + */ + public void blockCameraAccessIfNeeded(Set<Integer> runningUids) { + synchronized (mLock) { + for (int i = 0; i < mAppsToBlockOnVirtualDevice.size(); i++) { + final String cameraId = mAppsToBlockOnVirtualDevice.keyAt(i); + final OpenCameraInfo openCameraInfo = mAppsToBlockOnVirtualDevice.get(cameraId); + int packageUid = openCameraInfo.packageUid; + if (runningUids.contains(packageUid)) { + final String packageName = openCameraInfo.packageName; + InjectionSessionData data = mPackageToSessionData.get(packageName); + if (data == null) { + data = new InjectionSessionData(); + data.appUid = packageUid; + mPackageToSessionData.put(packageName, data); + } + startBlocking(packageName, cameraId); + } + } + } + } @Override public void close() { @@ -115,10 +156,13 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen public void onCameraOpened(@NonNull String cameraId, @NonNull String packageName) { synchronized (mLock) { try { - final ApplicationInfo ainfo = - mPackageManager.getApplicationInfo(packageName, 0); + final ApplicationInfo ainfo = mPackageManager.getApplicationInfo(packageName, 0); InjectionSessionData data = mPackageToSessionData.get(packageName); if (!mVirtualDeviceManagerInternal.isAppRunningOnAnyVirtualDevice(ainfo.uid)) { + OpenCameraInfo openCameraInfo = new OpenCameraInfo(); + openCameraInfo.packageName = packageName; + openCameraInfo.packageUid = ainfo.uid; + mAppsToBlockOnVirtualDevice.put(cameraId, openCameraInfo); CameraInjectionSession existingSession = (data != null) ? data.cameraIdToSession.get(cameraId) : null; if (existingSession != null) { @@ -149,6 +193,7 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen @Override public void onCameraClosed(@NonNull String cameraId) { synchronized (mLock) { + mAppsToBlockOnVirtualDevice.remove(cameraId); for (int i = mPackageToSessionData.size() - 1; i >= 0; i--) { InjectionSessionData data = mPackageToSessionData.valueAt(i); CameraInjectionSession session = data.cameraIdToSession.get(cameraId); @@ -168,6 +213,9 @@ class CameraAccessController extends CameraManager.AvailabilityCallback implemen */ private void startBlocking(String packageName, String cameraId) { try { + Slog.d( + TAG, + "startBlocking() cameraId: " + cameraId + " packageName: " + packageName); mCameraManager.injectCamera(packageName, cameraId, /* externalCamId */ "", mContext.getMainExecutor(), new CameraInjectionSession.InjectionStatusCallback() { diff --git a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java index 27de8cdc0421..0b437446826a 100644 --- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java +++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java @@ -93,9 +93,8 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController final ArraySet<Integer> mRunningUids = new ArraySet<>(); @Nullable private final ActivityListener mActivityListener; private final Handler mHandler = new Handler(Looper.getMainLooper()); - - @Nullable - private RunningAppsChangedListener mRunningAppsChangedListener; + private final ArraySet<RunningAppsChangedListener> mRunningAppsChangedListener = + new ArraySet<>(); /** * Creates a window policy controller that is generic to the different use cases of virtual @@ -142,9 +141,14 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController mActivityListener = activityListener; } - /** Sets listener for running applications change. */ - public void setRunningAppsChangedListener(@Nullable RunningAppsChangedListener listener) { - mRunningAppsChangedListener = listener; + /** Register a listener for running applications changes. */ + public void registerRunningAppsChangedListener(@NonNull RunningAppsChangedListener listener) { + mRunningAppsChangedListener.add(listener); + } + + /** Unregister a listener for running applications changes. */ + public void unregisterRunningAppsChangedListener(@NonNull RunningAppsChangedListener listener) { + mRunningAppsChangedListener.remove(listener); } @Override @@ -237,9 +241,11 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController mHandler.post(() -> mActivityListener.onDisplayEmpty(Display.INVALID_DISPLAY)); } } - if (mRunningAppsChangedListener != null) { - mRunningAppsChangedListener.onRunningAppsChanged(runningUids); - } + mHandler.post(() -> { + for (RunningAppsChangedListener listener : mRunningAppsChangedListener) { + listener.onRunningAppsChanged(runningUids); + } + }); } /** diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java index 90c879aee90a..de14ef61a075 100644 --- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java @@ -68,16 +68,18 @@ import android.window.DisplayWindowPolicyController; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.BlockedAppStreamingActivity; +import com.android.server.companion.virtual.GenericWindowPolicyController.RunningAppsChangedListener; import com.android.server.companion.virtual.audio.VirtualAudioController; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Map; import java.util.Set; +import java.util.function.Consumer; final class VirtualDeviceImpl extends IVirtualDevice.Stub - implements IBinder.DeathRecipient { + implements IBinder.DeathRecipient, RunningAppsChangedListener { private static final String TAG = "VirtualDeviceImpl"; @@ -101,6 +103,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub private final VirtualDeviceParams mParams; private final Map<Integer, PowerManager.WakeLock> mPerDisplayWakelocks = new ArrayMap<>(); private final IVirtualDeviceActivityListener mActivityListener; + @NonNull + private Consumer<ArraySet<Integer>> mRunningAppsChangedCallback; // The default setting for showing the pointer on new displays. @GuardedBy("mVirtualDeviceLock") private boolean mDefaultShowPointerIcon = true; @@ -139,21 +143,25 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub IBinder token, int ownerUid, OnDeviceCloseListener listener, PendingTrampolineCallback pendingTrampolineCallback, IVirtualDeviceActivityListener activityListener, + Consumer<ArraySet<Integer>> runningAppsChangedCallback, VirtualDeviceParams params) { this(context, associationInfo, token, ownerUid, /* inputController= */ null, listener, - pendingTrampolineCallback, activityListener, params); + pendingTrampolineCallback, activityListener, runningAppsChangedCallback, params); } @VisibleForTesting VirtualDeviceImpl(Context context, AssociationInfo associationInfo, IBinder token, int ownerUid, InputController inputController, OnDeviceCloseListener listener, PendingTrampolineCallback pendingTrampolineCallback, - IVirtualDeviceActivityListener activityListener, VirtualDeviceParams params) { + IVirtualDeviceActivityListener activityListener, + Consumer<ArraySet<Integer>> runningAppsChangedCallback, + VirtualDeviceParams params) { UserHandle ownerUserHandle = UserHandle.getUserHandleForUid(ownerUid); mContext = context.createContextAsUser(ownerUserHandle, 0); mAssociationInfo = associationInfo; mPendingTrampolineCallback = pendingTrampolineCallback; mActivityListener = activityListener; + mRunningAppsChangedCallback = runningAppsChangedCallback; mOwnerUid = ownerUid; mAppToken = token; mParams = params; @@ -278,6 +286,11 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub close(); } + @Override + public void onRunningAppsChanged(ArraySet<Integer> runningUids) { + mRunningAppsChangedCallback.accept(runningUids); + } + @VisibleForTesting VirtualAudioController getVirtualAudioControllerForTesting() { return mVirtualAudioController; @@ -529,7 +542,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub // reentrancy problems. mContext.getMainThreadHandler().post(() -> addWakeLockForDisplay(displayId)); - final GenericWindowPolicyController dwpc = + final GenericWindowPolicyController gwpc = new GenericWindowPolicyController(FLAG_SECURE, SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, getAllowedUserHandles(), @@ -540,8 +553,9 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub mParams.getDefaultActivityPolicy(), createListenerAdapter(displayId), activityInfo -> onActivityBlocked(displayId, activityInfo)); - mWindowPolicyControllers.put(displayId, dwpc); - return dwpc; + gwpc.registerRunningAppsChangedListener(/* listener= */ this); + mWindowPolicyControllers.put(displayId, gwpc); + return gwpc; } } @@ -599,6 +613,10 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub wakeLock.release(); mPerDisplayWakelocks.remove(displayId); } + GenericWindowPolicyController gwpc = mWindowPolicyControllers.get(displayId); + if (gwpc != null) { + gwpc.unregisterRunningAppsChangedListener(/* listener= */ this); + } mVirtualDisplayIds.remove(displayId); mWindowPolicyControllers.remove(displayId); } diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java index 9acca8025920..6398b2142e37 100644 --- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java @@ -251,7 +251,10 @@ public class VirtualDeviceManagerService extends SystemService { } } }, - this, activityListener, params); + this, activityListener, + runningUids -> cameraAccessController.blockCameraAccessIfNeeded( + runningUids), + params); if (cameraAccessController != null) { cameraAccessController.startObservingIfNeeded(); } else { diff --git a/services/companion/java/com/android/server/companion/virtual/audio/VirtualAudioController.java b/services/companion/java/com/android/server/companion/virtual/audio/VirtualAudioController.java index 13a47d681729..c91877aad47e 100644 --- a/services/companion/java/com/android/server/companion/virtual/audio/VirtualAudioController.java +++ b/services/companion/java/com/android/server/companion/virtual/audio/VirtualAudioController.java @@ -85,7 +85,7 @@ public final class VirtualAudioController implements AudioPlaybackCallback, @NonNull IAudioRoutingCallback routingCallback, @Nullable IAudioConfigChangedCallback configChangedCallback) { mGenericWindowPolicyController = genericWindowPolicyController; - mGenericWindowPolicyController.setRunningAppsChangedListener(/* listener= */ this); + mGenericWindowPolicyController.registerRunningAppsChangedListener(/* listener= */ this); synchronized (mCallbackLock) { mRoutingCallback = routingCallback; mConfigChangedCallback = configChangedCallback; @@ -111,7 +111,8 @@ public final class VirtualAudioController implements AudioPlaybackCallback, mAudioPlaybackDetector.unregister(); mAudioRecordingDetector.unregister(); if (mGenericWindowPolicyController != null) { - mGenericWindowPolicyController.setRunningAppsChangedListener(/* listener= */ null); + mGenericWindowPolicyController.unregisterRunningAppsChangedListener( + /* listener= */ this); mGenericWindowPolicyController = null; } synchronized (mCallbackLock) { diff --git a/services/core/java/com/android/server/BinaryTransparencyService.java b/services/core/java/com/android/server/BinaryTransparencyService.java index 1f8ef8226c32..877ee8218ea6 100644 --- a/services/core/java/com/android/server/BinaryTransparencyService.java +++ b/services/core/java/com/android/server/BinaryTransparencyService.java @@ -441,6 +441,7 @@ public class BinaryTransparencyService extends SystemService { final JobInfo jobInfo = new JobInfo.Builder(COMPUTE_APEX_MODULE_SHA256_JOB_ID, new ComponentName(context, UpdateMeasurementsJobService.class)) .setRequiresDeviceIdle(true) + .setRequiresCharging(true) .build(); if (jobScheduler.schedule(jobInfo) != JobScheduler.RESULT_SUCCESS) { Slog.e(TAG, "Failed to schedule job to update binary measurements."); diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java index f944d4fd8478..e529010e6b7d 100644 --- a/services/core/java/com/android/server/GestureLauncherService.java +++ b/services/core/java/com/android/server/GestureLauncherService.java @@ -75,6 +75,13 @@ public class GestureLauncherService extends SystemService { @VisibleForTesting static final long CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS = 300; /** + * Min time in milliseconds to complete the emergency gesture for it count. If the gesture is + * completed faster than this, we assume it's not performed by human and the + * event gets ignored. + */ + @VisibleForTesting static final int EMERGENCY_GESTURE_TAP_DETECTION_MIN_TIME_MS = 160; + + /** * Interval in milliseconds in which the power button must be depressed in succession to be * considered part of an extended sequence of taps. Note that this is a looser threshold than * the camera launch gesture, because the purpose of this threshold is to measure the @@ -184,6 +191,7 @@ public class GestureLauncherService extends SystemService { private int mEmergencyGesturePowerButtonCooldownPeriodMs; private long mLastPowerDown; + private long mFirstPowerDown; private long mLastEmergencyGestureTriggered; private int mPowerButtonConsecutiveTaps; private int mPowerButtonSlowConsecutiveTaps; @@ -553,10 +561,12 @@ public class GestureLauncherService extends SystemService { mLastPowerDown = event.getEventTime(); if (powerTapInterval >= POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS) { // Tap too slow, reset consecutive tap counts. + mFirstPowerDown = event.getEventTime(); mPowerButtonConsecutiveTaps = 1; mPowerButtonSlowConsecutiveTaps = 1; } else if (powerTapInterval >= CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS) { // Tap too slow for shortcuts + mFirstPowerDown = event.getEventTime(); mPowerButtonConsecutiveTaps = 1; mPowerButtonSlowConsecutiveTaps++; } else { @@ -575,7 +585,26 @@ public class GestureLauncherService extends SystemService { intercept = interactive; } if (mPowerButtonConsecutiveTaps == EMERGENCY_GESTURE_POWER_TAP_COUNT_THRESHOLD) { - launchEmergencyGesture = true; + long emergencyGestureSpentTime = event.getEventTime() - mFirstPowerDown; + long emergencyGestureTapDetectionMinTimeMs = Settings.Global.getInt( + mContext.getContentResolver(), + Settings.Global.EMERGENCY_GESTURE_TAP_DETECTION_MIN_TIME_MS, + EMERGENCY_GESTURE_TAP_DETECTION_MIN_TIME_MS); + if (emergencyGestureSpentTime <= emergencyGestureTapDetectionMinTimeMs) { + Slog.i(TAG, "Emergency gesture detected but it's too fast. Gesture time: " + + emergencyGestureSpentTime + " ms"); + // Reset consecutive tap counts. + mFirstPowerDown = event.getEventTime(); + mPowerButtonConsecutiveTaps = 1; + mPowerButtonSlowConsecutiveTaps = 1; + } else { + Slog.i(TAG, "Emergency gesture detected. Gesture time: " + + emergencyGestureSpentTime + " ms"); + launchEmergencyGesture = true; + mMetricsLogger.histogram("emergency_gesture_spent_time", + (int) emergencyGestureSpentTime); + + } } } if (mCameraDoubleTapPowerEnabled diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java index 2d328d8b0949..eefeee3918b3 100644 --- a/services/core/java/com/android/server/VcnManagementService.java +++ b/services/core/java/com/android/server/VcnManagementService.java @@ -87,6 +87,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -153,7 +154,7 @@ import java.util.concurrent.TimeUnit; public class VcnManagementService extends IVcnManagementService.Stub { @NonNull private static final String TAG = VcnManagementService.class.getSimpleName(); private static final long DUMP_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(5); - private static final int LOCAL_LOG_LINE_COUNT = 128; + private static final int LOCAL_LOG_LINE_COUNT = 512; // Public for use in all other VCN classes @NonNull public static final LocalLog LOCAL_LOG = new LocalLog(LOCAL_LOG_LINE_COUNT); @@ -172,7 +173,7 @@ public class VcnManagementService extends IVcnManagementService.Stub { @NonNull private final VcnNetworkProvider mNetworkProvider; @NonNull private final TelephonySubscriptionTrackerCallback mTelephonySubscriptionTrackerCb; @NonNull private final TelephonySubscriptionTracker mTelephonySubscriptionTracker; - @NonNull private final BroadcastReceiver mPkgChangeReceiver; + @NonNull private final BroadcastReceiver mVcnBroadcastReceiver; @NonNull private final TrackingNetworkCallback mTrackingNetworkCallback = new TrackingNetworkCallback(); @@ -217,28 +218,17 @@ public class VcnManagementService extends IVcnManagementService.Stub { mConfigDiskRwHelper = mDeps.newPersistableBundleLockingReadWriteHelper(VCN_CONFIG_FILE); - mPkgChangeReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - - if (Intent.ACTION_PACKAGE_ADDED.equals(action) - || Intent.ACTION_PACKAGE_REPLACED.equals(action) - || Intent.ACTION_PACKAGE_REMOVED.equals(action)) { - mTelephonySubscriptionTracker.handleSubscriptionsChanged(); - } else { - Log.wtf(TAG, "received unexpected intent: " + action); - } - } - }; + mVcnBroadcastReceiver = new VcnBroadcastReceiver(); final IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED); intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); + intentFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED); + intentFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED); intentFilter.addDataScheme("package"); mContext.registerReceiver( - mPkgChangeReceiver, intentFilter, null /* broadcastPermission */, mHandler); + mVcnBroadcastReceiver, intentFilter, null /* broadcastPermission */, mHandler); // Run on handler to ensure I/O does not block system server startup mHandler.post(() -> { @@ -443,6 +433,53 @@ public class VcnManagementService extends IVcnManagementService.Stub { return Objects.equals(subGrp, snapshot.getActiveDataSubscriptionGroup()); } + private class VcnBroadcastReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + + switch (action) { + case Intent.ACTION_PACKAGE_ADDED: // Fallthrough + case Intent.ACTION_PACKAGE_REPLACED: // Fallthrough + case Intent.ACTION_PACKAGE_REMOVED: + // Reevaluate subscriptions + mTelephonySubscriptionTracker.handleSubscriptionsChanged(); + + break; + case Intent.ACTION_PACKAGE_FULLY_REMOVED: + case Intent.ACTION_PACKAGE_DATA_CLEARED: + final String pkgName = intent.getData().getSchemeSpecificPart(); + + if (pkgName == null || pkgName.isEmpty()) { + logWtf("Package name was empty or null for intent with action" + action); + return; + } + + // Clear configs for the packages that had data cleared, or removed. + synchronized (mLock) { + final List<ParcelUuid> toRemove = new ArrayList<>(); + for (Entry<ParcelUuid, VcnConfig> entry : mConfigs.entrySet()) { + if (pkgName.equals(entry.getValue().getProvisioningPackageName())) { + toRemove.add(entry.getKey()); + } + } + + for (ParcelUuid subGrp : toRemove) { + stopAndClearVcnConfigInternalLocked(subGrp); + } + + if (!toRemove.isEmpty()) { + writeConfigsToDiskLocked(); + } + } + + break; + default: + Slog.wtf(TAG, "received unexpected intent: " + action); + } + } + } + private class VcnSubscriptionTrackerCallback implements TelephonySubscriptionTrackerCallback { /** * Handles subscription group changes, as notified by {@link TelephonySubscriptionTracker} @@ -456,7 +493,7 @@ public class VcnManagementService extends IVcnManagementService.Stub { synchronized (mLock) { final TelephonySubscriptionSnapshot oldSnapshot = mLastSnapshot; mLastSnapshot = snapshot; - logDbg("new snapshot: " + mLastSnapshot); + logInfo("new snapshot: " + mLastSnapshot); // Start any VCN instances as necessary for (Entry<ParcelUuid, VcnConfig> entry : mConfigs.entrySet()) { @@ -504,6 +541,7 @@ public class VcnManagementService extends IVcnManagementService.Stub { final Map<ParcelUuid, Set<Integer>> currSubGrpMappings = getSubGroupToSubIdMappings(mLastSnapshot); if (!currSubGrpMappings.equals(oldSubGrpMappings)) { + garbageCollectAndWriteVcnConfigsLocked(); notifyAllPolicyListenersLocked(); } } @@ -522,6 +560,8 @@ public class VcnManagementService extends IVcnManagementService.Stub { @GuardedBy("mLock") private void stopVcnLocked(@NonNull ParcelUuid uuidToTeardown) { + logInfo("Stopping VCN config for subGrp: " + uuidToTeardown); + // Remove in 2 steps. Make sure teardownAsync is triggered before removing from the map. final Vcn vcnToTeardown = mVcns.get(uuidToTeardown); if (vcnToTeardown == null) { @@ -567,7 +607,7 @@ public class VcnManagementService extends IVcnManagementService.Stub { @GuardedBy("mLock") private void startVcnLocked(@NonNull ParcelUuid subscriptionGroup, @NonNull VcnConfig config) { - logDbg("Starting VCN config for subGrp: " + subscriptionGroup); + logInfo("Starting VCN config for subGrp: " + subscriptionGroup); // TODO(b/193687515): Support multiple VCNs active at the same time if (!mVcns.isEmpty()) { @@ -626,7 +666,7 @@ public class VcnManagementService extends IVcnManagementService.Stub { if (!config.getProvisioningPackageName().equals(opPkgName)) { throw new IllegalArgumentException("Mismatched caller and VcnConfig creator"); } - logDbg("VCN config updated for subGrp: " + subscriptionGroup); + logInfo("VCN config updated for subGrp: " + subscriptionGroup); mContext.getSystemService(AppOpsManager.class) .checkPackage(mDeps.getBinderCallingUid(), config.getProvisioningPackageName()); @@ -643,6 +683,39 @@ public class VcnManagementService extends IVcnManagementService.Stub { }); } + private void enforceCarrierPrivilegeOrProvisioningPackage( + @NonNull ParcelUuid subscriptionGroup, @NonNull String pkg) { + // Only apps running in the primary (system) user are allowed to configure the VCN. This is + // in line with Telephony's behavior with regards to binding to a Carrier App provided + // CarrierConfigService. + enforcePrimaryUser(); + + if (isProvisioningPackageForConfig(subscriptionGroup, pkg)) { + return; + } + + // Must NOT be called from cleared binder identity, since this checks user calling identity + enforceCallingUserAndCarrierPrivilege(subscriptionGroup, pkg); + } + + private boolean isProvisioningPackageForConfig( + @NonNull ParcelUuid subscriptionGroup, @NonNull String pkg) { + // Try-finally to return early if matching owned subscription found. + final long identity = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + final VcnConfig config = mConfigs.get(subscriptionGroup); + if (config != null && pkg.equals(config.getProvisioningPackageName())) { + return true; + } + } + } finally { + Binder.restoreCallingIdentity(identity); + } + + return false; + } + /** * Clears the VcnManagementService for a given subscription group. * @@ -652,35 +725,60 @@ public class VcnManagementService extends IVcnManagementService.Stub { public void clearVcnConfig(@NonNull ParcelUuid subscriptionGroup, @NonNull String opPkgName) { requireNonNull(subscriptionGroup, "subscriptionGroup was null"); requireNonNull(opPkgName, "opPkgName was null"); - logDbg("VCN config cleared for subGrp: " + subscriptionGroup); + logInfo("VCN config cleared for subGrp: " + subscriptionGroup); mContext.getSystemService(AppOpsManager.class) .checkPackage(mDeps.getBinderCallingUid(), opPkgName); - enforceCallingUserAndCarrierPrivilege(subscriptionGroup, opPkgName); + enforceCarrierPrivilegeOrProvisioningPackage(subscriptionGroup, opPkgName); Binder.withCleanCallingIdentity(() -> { synchronized (mLock) { - mConfigs.remove(subscriptionGroup); - final boolean vcnExists = mVcns.containsKey(subscriptionGroup); + stopAndClearVcnConfigInternalLocked(subscriptionGroup); + writeConfigsToDiskLocked(); + } + }); + } - stopVcnLocked(subscriptionGroup); + private void stopAndClearVcnConfigInternalLocked(@NonNull ParcelUuid subscriptionGroup) { + mConfigs.remove(subscriptionGroup); + final boolean vcnExists = mVcns.containsKey(subscriptionGroup); - if (vcnExists) { - // TODO(b/181789060): invoke asynchronously after Vcn notifies through - // VcnCallback - notifyAllPermissionedStatusCallbacksLocked( - subscriptionGroup, VCN_STATUS_CODE_NOT_CONFIGURED); - } + stopVcnLocked(subscriptionGroup); - writeConfigsToDiskLocked(); + if (vcnExists) { + // TODO(b/181789060): invoke asynchronously after Vcn notifies through + // VcnCallback + notifyAllPermissionedStatusCallbacksLocked( + subscriptionGroup, VCN_STATUS_CODE_NOT_CONFIGURED); + } + } + + private void garbageCollectAndWriteVcnConfigsLocked() { + final SubscriptionManager subMgr = mContext.getSystemService(SubscriptionManager.class); + + boolean shouldWrite = false; + + final Iterator<ParcelUuid> configsIterator = mConfigs.keySet().iterator(); + while (configsIterator.hasNext()) { + final ParcelUuid subGrp = configsIterator.next(); + + final List<SubscriptionInfo> subscriptions = subMgr.getSubscriptionsInGroup(subGrp); + if (subscriptions == null || subscriptions.isEmpty()) { + // Trim subGrps with no more subscriptions; must have moved to another subGrp + configsIterator.remove(); + shouldWrite = true; } - }); + } + + if (shouldWrite) { + writeConfigsToDiskLocked(); + } } /** * Retrieves the list of subscription groups with configured VcnConfigs * - * <p>Limited to subscription groups for which the caller is carrier privileged. + * <p>Limited to subscription groups for which the caller had configured. * * <p>Implements the IVcnManagementService Binder interface. */ @@ -696,7 +794,8 @@ public class VcnManagementService extends IVcnManagementService.Stub { final List<ParcelUuid> result = new ArrayList<>(); synchronized (mLock) { for (ParcelUuid subGrp : mConfigs.keySet()) { - if (mLastSnapshot.packageHasPermissionsForSubscriptionGroup(subGrp, opPkgName)) { + if (mLastSnapshot.packageHasPermissionsForSubscriptionGroup(subGrp, opPkgName) + || isProvisioningPackageForConfig(subGrp, opPkgName)) { result.add(subGrp); } } @@ -1050,24 +1149,34 @@ public class VcnManagementService extends IVcnManagementService.Stub { Slog.d(TAG, msg, tr); } + private void logInfo(String msg) { + Slog.i(TAG, msg); + LOCAL_LOG.log("[INFO] [" + TAG + "] " + msg); + } + + private void logInfo(String msg, Throwable tr) { + Slog.i(TAG, msg, tr); + LOCAL_LOG.log("[INFO] [" + TAG + "] " + msg + tr); + } + private void logErr(String msg) { Slog.e(TAG, msg); - LOCAL_LOG.log(TAG + " ERR: " + msg); + LOCAL_LOG.log("[ERR] [" + TAG + "] " + msg); } private void logErr(String msg, Throwable tr) { Slog.e(TAG, msg, tr); - LOCAL_LOG.log(TAG + " ERR: " + msg + tr); + LOCAL_LOG.log("[ERR ] [" + TAG + "] " + msg + tr); } private void logWtf(String msg) { Slog.wtf(TAG, msg); - LOCAL_LOG.log(TAG + " WTF: " + msg); + LOCAL_LOG.log("[WTF] [" + TAG + "] " + msg); } private void logWtf(String msg, Throwable tr) { Slog.wtf(TAG, msg, tr); - LOCAL_LOG.log(TAG + " WTF: " + msg + tr); + LOCAL_LOG.log("[WTF ] [" + TAG + "] " + msg + tr); } /** diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index efde2a52f4dc..7cee203d0bf0 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -49,6 +49,12 @@ import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE; import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_DATA_SAVER; +import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRICTED; +import static android.net.ConnectivityManager.BLOCKED_REASON_APP_STANDBY; +import static android.net.ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER; +import static android.net.ConnectivityManager.BLOCKED_REASON_DOZE; +import static android.net.ConnectivityManager.BLOCKED_REASON_LOW_POWER_STANDBY; import static android.net.ConnectivityManager.BLOCKED_REASON_NONE; import static android.os.FactoryTest.FACTORY_TEST_OFF; import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL; @@ -4815,7 +4821,7 @@ public class ActivityManagerService extends IActivityManager.Stub } checkTime(startTime, "attachApplicationLocked: immediately before bindApplication"); - bindApplicationTimeMillis = SystemClock.elapsedRealtime(); + bindApplicationTimeMillis = SystemClock.uptimeMillis(); mAtmInternal.preBindApplication(app.getWindowProcessController()); final ActiveInstrumentation instr2 = app.getActiveInstrumentation(); if (mPlatformCompat != null) { @@ -4963,9 +4969,9 @@ public class ActivityManagerService extends IActivityManager.Stub pid, app.info.packageName, FrameworkStatsLog.PROCESS_START_TIME__TYPE__COLD, - app.getStartTime(), - (int) (bindApplicationTimeMillis - app.getStartTime()), - (int) (SystemClock.elapsedRealtime() - app.getStartTime()), + app.getStartElapsedTime(), + (int) (bindApplicationTimeMillis - app.getStartUptime()), + (int) (SystemClock.uptimeMillis() - app.getStartUptime()), app.getHostingRecord().getType(), (app.getHostingRecord().getName() != null ? app.getHostingRecord().getName() : "")); return true; @@ -15087,7 +15093,7 @@ public class ActivityManagerService extends IActivityManager.Stub @GuardedBy("this") final boolean canGcNowLocked() { for (BroadcastQueue q : mBroadcastQueues) { - if (!q.mParallelBroadcasts.isEmpty() || !q.mDispatcher.isEmpty()) { + if (!q.mParallelBroadcasts.isEmpty() || !q.mDispatcher.isIdle()) { return false; } } @@ -17306,8 +17312,22 @@ public class ActivityManagerService extends IActivityManager.Stub // TODO: We can reuse this data in // ProcessList#incrementProcStateSeqAndNotifyAppsLOSP instead of calling into // NetworkManagementService. - return mUidNetworkBlockedReasons.get(uid, BLOCKED_REASON_NONE) - != BLOCKED_REASON_NONE; + final int uidBlockedReasons = mUidNetworkBlockedReasons.get( + uid, BLOCKED_REASON_NONE); + if (uidBlockedReasons == BLOCKED_REASON_NONE) { + return false; + } + final int topExemptedBlockedReasons = BLOCKED_REASON_BATTERY_SAVER + | BLOCKED_REASON_DOZE + | BLOCKED_REASON_APP_STANDBY + | BLOCKED_REASON_LOW_POWER_STANDBY + | BLOCKED_METERED_REASON_DATA_SAVER + | BLOCKED_METERED_REASON_USER_RESTRICTED; + final int effectiveBlockedReasons = + uidBlockedReasons & ~topExemptedBlockedReasons; + // Only consider it as blocked if it is not blocked by a reason + // that is not exempted by app being in the top state. + return effectiveBlockedReasons == BLOCKED_REASON_NONE; } } diff --git a/services/core/java/com/android/server/am/AppBatteryTracker.java b/services/core/java/com/android/server/am/AppBatteryTracker.java index 64ff532b026a..8c42d4d1bd5a 100644 --- a/services/core/java/com/android/server/am/AppBatteryTracker.java +++ b/services/core/java/com/android/server/am/AppBatteryTracker.java @@ -266,22 +266,16 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> } FrameworkStatsLog.write(FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO, uid, - FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__RESTRICTION_LEVEL__LEVEL_UNKNOWN, - FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__THRESHOLD__THRESHOLD_UNKNOWN, - FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__TRACKER__UNKNOWN_TRACKER, + AppBackgroundRestrictionsInfo.LEVEL_UNKNOWN, // RestrictionLevel + AppBackgroundRestrictionsInfo.THRESHOLD_UNKNOWN, + AppBackgroundRestrictionsInfo.UNKNOWN_TRACKER, null /*byte[] fgs_tracker_info*/, getBatteryTrackerInfoProtoLocked(uid) /*byte[] battery_tracker_info*/, null /*byte[] broadcast_events_tracker_info*/, null /*byte[] bind_service_events_tracker_info*/, - FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_UNKNOWN, - FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__OPT_LEVEL__UNKNOWN, - FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__TARGET_SDK__SDK_UNKNOWN, + AppBackgroundRestrictionsInfo.REASON_UNKNOWN, // ExemptionReason + AppBackgroundRestrictionsInfo.UNKNOWN, // OptimizationLevel + AppBackgroundRestrictionsInfo.SDK_UNKNOWN, // TargetSdk isLowRamDeviceStatic()); } } @@ -654,7 +648,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> final long start = stats.getStatsStartTimestamp(); final long end = stats.getStatsEndTimestamp(); final double scale = expectedDuration > 0 - ? (expectedDuration * 1.0d) / (end - start) : 1.0d; + ? Math.min((expectedDuration * 1.0d) / (end - start), 1.0d) : 1.0d; final AppBatteryPolicy bgPolicy = mInjector.getPolicy(); for (UidBatteryConsumer uidConsumer : uidConsumers) { // TODO: b/200326767 - as we are not supporting per proc state attribution yet, diff --git a/services/core/java/com/android/server/am/AppRestrictionController.java b/services/core/java/com/android/server/am/AppRestrictionController.java index 798647e04325..d70404fb6a65 100644 --- a/services/core/java/com/android/server/am/AppRestrictionController.java +++ b/services/core/java/com/android/server/am/AppRestrictionController.java @@ -116,6 +116,7 @@ import android.content.pm.ServiceInfo.ForegroundServiceType; import android.database.ContentObserver; import android.graphics.drawable.Icon; import android.net.Uri; +import android.os.AppBackgroundRestrictionsInfo; import android.os.Build; import android.os.Environment; import android.os.Handler; @@ -123,7 +124,6 @@ import android.os.HandlerExecutor; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; -import android.os.PowerExemptionManager.ExemptionReason; import android.os.PowerExemptionManager.ReasonCode; import android.os.RemoteException; import android.os.SystemClock; @@ -223,6 +223,11 @@ public final class AppRestrictionController { private static final String ATTR_LEVEL_TS = "levelts"; private static final String ATTR_REASON = "reason"; + private static final String[] ROLES_IN_INTEREST = { + RoleManager.ROLE_DIALER, + RoleManager.ROLE_EMERGENCY, + }; + private final Context mContext; private final HandlerThread mBgHandlerThread; private final BgHandler mBgHandler; @@ -1090,6 +1095,14 @@ public final class AppRestrictionController { DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "restriction_exempted_packages"; /** + * Whether or not to show the notification for abusive apps, i.e. when the system + * detects it's draining significant amount of battery in the background. + * {@code true} - we'll show the prompt to user, {@code false} - we'll not show it. + */ + static final String KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED = + DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "prompt_abusive_apps_to_bg_restricted"; + + /** * Default value to {@link #mBgAutoRestrictedBucket}. */ static final boolean DEFAULT_BG_AUTO_RESTRICTED_BUCKET_ON_BG_RESTRICTION = false; @@ -1114,6 +1127,11 @@ public final class AppRestrictionController { */ final boolean mDefaultBgPromptFgsWithNotiToBgRestricted; + /** + * Default value to {@link #mBgPromptAbusiveAppsToBgRestricted}. + */ + final boolean mDefaultBgPromptAbusiveAppToBgRestricted; + volatile boolean mBgAutoRestrictedBucket; volatile boolean mRestrictedBucketEnabled; @@ -1139,10 +1157,17 @@ public final class AppRestrictionController { */ volatile boolean mBgPromptFgsWithNotiOnLongRunning; + /** + * @see #KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED. + */ + volatile boolean mBgPromptAbusiveAppsToBgRestricted; + ConstantsObserver(Handler handler, Context context) { super(handler); mDefaultBgPromptFgsWithNotiToBgRestricted = context.getResources().getBoolean( com.android.internal.R.bool.config_bg_prompt_fgs_with_noti_to_bg_restricted); + mDefaultBgPromptAbusiveAppToBgRestricted = context.getResources().getBoolean( + com.android.internal.R.bool.config_bg_prompt_abusive_apps_to_bg_restricted); } @Override @@ -1167,6 +1192,9 @@ public final class AppRestrictionController { case KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING: updateBgPromptFgsWithNotiOnLongRunning(); break; + case KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED: + updateBgPromptAbusiveAppToBgRestricted(); + break; case KEY_BG_RESTRICTION_EXEMPTED_PACKAGES: updateBgRestrictionExemptedPackages(); break; @@ -1204,6 +1232,7 @@ public final class AppRestrictionController { updateBgLongFgsNotificationMinimalInterval(); updateBgPromptFgsWithNotiToBgRestricted(); updateBgPromptFgsWithNotiOnLongRunning(); + updateBgPromptAbusiveAppToBgRestricted(); updateBgRestrictionExemptedPackages(); } @@ -1246,6 +1275,13 @@ public final class AppRestrictionController { DEFAULT_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING); } + private void updateBgPromptAbusiveAppToBgRestricted() { + mBgPromptAbusiveAppsToBgRestricted = DeviceConfig.getBoolean( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED, + mDefaultBgPromptAbusiveAppToBgRestricted); + } + private void updateBgRestrictionExemptedPackages() { final String settings = DeviceConfig.getString( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, @@ -1285,6 +1321,10 @@ public final class AppRestrictionController { pw.print('='); pw.println(mBgPromptFgsWithNotiToBgRestricted); pw.print(prefix); + pw.print(KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED); + pw.print('='); + pw.println(mBgPromptAbusiveAppsToBgRestricted); + pw.print(prefix); pw.print(KEY_BG_RESTRICTION_EXEMPTED_PACKAGES); pw.print('='); pw.println(mBgRestrictionExemptedPackages.toString()); @@ -1386,6 +1426,7 @@ public final class AppRestrictionController { initBgRestrictionExemptioFromSysConfig(); initRestrictionStates(); initSystemModuleNames(); + initRolesInInterest(); registerForUidObservers(); registerForSystemBroadcasts(); mNotificationHelper.onSystemReady(); @@ -1875,76 +1916,59 @@ public final class AppRestrictionController { private int getRestrictionLevelStatsd(@RestrictionLevel int level) { switch (level) { case RESTRICTION_LEVEL_UNKNOWN: - return FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__RESTRICTION_LEVEL__LEVEL_UNKNOWN; + return AppBackgroundRestrictionsInfo.LEVEL_UNKNOWN; case RESTRICTION_LEVEL_UNRESTRICTED: - return FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__RESTRICTION_LEVEL__LEVEL_UNRESTRICTED; + return AppBackgroundRestrictionsInfo.LEVEL_UNRESTRICTED; case RESTRICTION_LEVEL_EXEMPTED: - return FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__RESTRICTION_LEVEL__LEVEL_EXEMPTED; + return AppBackgroundRestrictionsInfo.LEVEL_EXEMPTED; case RESTRICTION_LEVEL_ADAPTIVE_BUCKET: - return FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__RESTRICTION_LEVEL__LEVEL_ADAPTIVE_BUCKET; + return AppBackgroundRestrictionsInfo.LEVEL_ADAPTIVE_BUCKET; case RESTRICTION_LEVEL_RESTRICTED_BUCKET: - return FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__RESTRICTION_LEVEL__LEVEL_RESTRICTED_BUCKET; + return AppBackgroundRestrictionsInfo.LEVEL_RESTRICTED_BUCKET; case RESTRICTION_LEVEL_BACKGROUND_RESTRICTED: - return FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__RESTRICTION_LEVEL__LEVEL_BACKGROUND_RESTRICTED; + return AppBackgroundRestrictionsInfo.LEVEL_BACKGROUND_RESTRICTED; case RESTRICTION_LEVEL_HIBERNATION: - return FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__RESTRICTION_LEVEL__LEVEL_HIBERNATION; + return AppBackgroundRestrictionsInfo.LEVEL_HIBERNATION; default: - return FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__RESTRICTION_LEVEL__LEVEL_UNKNOWN; + return AppBackgroundRestrictionsInfo.LEVEL_UNKNOWN; } } private int getThresholdStatsd(int reason) { switch (reason) { case REASON_MAIN_FORCED_BY_SYSTEM: - return FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__THRESHOLD__THRESHOLD_RESTRICTED; + return AppBackgroundRestrictionsInfo.THRESHOLD_RESTRICTED; case REASON_MAIN_FORCED_BY_USER: - return FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__THRESHOLD__THRESHOLD_USER; + return AppBackgroundRestrictionsInfo.THRESHOLD_USER; default: - return FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__THRESHOLD__THRESHOLD_UNKNOWN; + return AppBackgroundRestrictionsInfo.THRESHOLD_UNKNOWN; } } private int getTrackerTypeStatsd(@TrackerType int type) { switch (type) { case TRACKER_TYPE_BATTERY: - return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__TRACKER__BATTERY_TRACKER; + return AppBackgroundRestrictionsInfo.BATTERY_TRACKER; case TRACKER_TYPE_BATTERY_EXEMPTION: - return FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__TRACKER__BATTERY_EXEMPTION_TRACKER; + return AppBackgroundRestrictionsInfo.BATTERY_EXEMPTION_TRACKER; case TRACKER_TYPE_FGS: - return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__TRACKER__FGS_TRACKER; + return AppBackgroundRestrictionsInfo.FGS_TRACKER; case TRACKER_TYPE_MEDIA_SESSION: - return FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__TRACKER__MEDIA_SESSION_TRACKER; + return AppBackgroundRestrictionsInfo.MEDIA_SESSION_TRACKER; case TRACKER_TYPE_PERMISSION: - return FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__TRACKER__PERMISSION_TRACKER; + return AppBackgroundRestrictionsInfo.PERMISSION_TRACKER; case TRACKER_TYPE_BROADCAST_EVENTS: - return FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__TRACKER__BROADCAST_EVENTS_TRACKER; + return AppBackgroundRestrictionsInfo.BROADCAST_EVENTS_TRACKER; case TRACKER_TYPE_BIND_SERVICE_EVENTS: - return FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__TRACKER__BIND_SERVICE_EVENTS_TRACKER; + return AppBackgroundRestrictionsInfo.BIND_SERVICE_EVENTS_TRACKER; default: - return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__TRACKER__UNKNOWN_TRACKER; + return AppBackgroundRestrictionsInfo.UNKNOWN_TRACKER; } } - private @ExemptionReason int getExemptionReasonStatsd(int uid, @RestrictionLevel int level) { + private int getExemptionReasonStatsd(int uid, @RestrictionLevel int level) { if (level != RESTRICTION_LEVEL_EXEMPTED) { - return FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_DENIED; + return AppBackgroundRestrictionsInfo.REASON_DENIED; } @ReasonCode final int reasonCode = getBackgroundRestrictionExemptionReason(uid); @@ -1954,16 +1978,15 @@ public final class AppRestrictionController { private int getOptimizationLevelStatsd(@RestrictionLevel int level) { switch (level) { case RESTRICTION_LEVEL_UNKNOWN: - return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__OPT_LEVEL__UNKNOWN; + return AppBackgroundRestrictionsInfo.UNKNOWN; case RESTRICTION_LEVEL_UNRESTRICTED: - return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__OPT_LEVEL__NOT_OPTIMIZED; + return AppBackgroundRestrictionsInfo.NOT_OPTIMIZED; case RESTRICTION_LEVEL_ADAPTIVE_BUCKET: - return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__OPT_LEVEL__OPTIMIZED; + return AppBackgroundRestrictionsInfo.OPTIMIZED; case RESTRICTION_LEVEL_BACKGROUND_RESTRICTED: - return FrameworkStatsLog - .APP_BACKGROUND_RESTRICTIONS_INFO__OPT_LEVEL__BACKGROUND_RESTRICTED; + return AppBackgroundRestrictionsInfo.BACKGROUND_RESTRICTED; default: - return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__OPT_LEVEL__UNKNOWN; + return AppBackgroundRestrictionsInfo.UNKNOWN; } } @@ -1971,26 +1994,26 @@ public final class AppRestrictionController { private int getTargetSdkStatsd(String packageName) { final PackageManager pm = mInjector.getPackageManager(); if (pm == null) { - return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__TARGET_SDK__SDK_UNKNOWN; + return AppBackgroundRestrictionsInfo.SDK_UNKNOWN; } try { final PackageInfo pkg = pm.getPackageInfo(packageName, 0 /* flags */); if (pkg == null || pkg.applicationInfo == null) { - return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__TARGET_SDK__SDK_UNKNOWN; + return AppBackgroundRestrictionsInfo.SDK_UNKNOWN; } final int targetSdk = pkg.applicationInfo.targetSdkVersion; if (targetSdk < Build.VERSION_CODES.S) { - return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__TARGET_SDK__SDK_PRE_S; + return AppBackgroundRestrictionsInfo.SDK_PRE_S; } else if (targetSdk < Build.VERSION_CODES.TIRAMISU) { - return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__TARGET_SDK__SDK_S; + return AppBackgroundRestrictionsInfo.SDK_S; } else if (targetSdk == Build.VERSION_CODES.TIRAMISU) { - return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__TARGET_SDK__SDK_T; + return AppBackgroundRestrictionsInfo.SDK_T; } else { - return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__TARGET_SDK__SDK_UNKNOWN; + return AppBackgroundRestrictionsInfo.SDK_UNKNOWN; } } catch (PackageManager.NameNotFoundException ignored) { } - return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__TARGET_SDK__SDK_UNKNOWN; + return AppBackgroundRestrictionsInfo.SDK_UNKNOWN; } private void applyRestrictionLevel(String pkgName, int uid, @@ -2290,9 +2313,16 @@ public final class AppRestrictionController { } void postRequestBgRestrictedIfNecessary(String packageName, int uid) { + if (!mBgController.mConstantsObserver.mBgPromptAbusiveAppsToBgRestricted) { + if (DEBUG_BG_RESTRICTION_CONTROLLER) { + Slog.i(TAG, "Not requesting bg-restriction due to config"); + } + return; + } + final Intent intent = new Intent(Settings.ACTION_VIEW_ADVANCED_POWER_USAGE_DETAIL); intent.setData(Uri.fromParts(PACKAGE_SCHEME, packageName, null)); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); final PendingIntent pendingIntent = PendingIntent.getActivityAsUser(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE, null, @@ -2356,7 +2386,7 @@ public final class AppRestrictionController { } else { final Intent intent = new Intent(Settings.ACTION_VIEW_ADVANCED_POWER_USAGE_DETAIL); intent.setData(Uri.fromParts(PACKAGE_SCHEME, packageName, null)); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); pendingIntent = PendingIntent.getActivityAsUser(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE, null, UserHandle.of(UserHandle.getUserId(uid))); @@ -2666,6 +2696,18 @@ public final class AppRestrictionController { } } + private void initRolesInInterest() { + final int[] allUsers = mInjector.getUserManagerInternal().getUserIds(); + for (String role : ROLES_IN_INTEREST) { + if (mInjector.getRoleManager().isRoleAvailable(role)) { + for (int userId : allUsers) { + final UserHandle user = UserHandle.of(userId); + onRoleHoldersChanged(role, user); + } + } + } + } + private void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) { final List<String> rolePkgs = mInjector.getRoleManager().getRoleHoldersAsUser( roleName, user); diff --git a/services/core/java/com/android/server/am/BroadcastDispatcher.java b/services/core/java/com/android/server/am/BroadcastDispatcher.java index 872531a47bc9..49477ad75302 100644 --- a/services/core/java/com/android/server/am/BroadcastDispatcher.java +++ b/services/core/java/com/android/server/am/BroadcastDispatcher.java @@ -512,12 +512,24 @@ public class BroadcastDispatcher { */ public boolean isEmpty() { synchronized (mLock) { + return isIdle() + && getBootCompletedBroadcastsUidsSize(Intent.ACTION_LOCKED_BOOT_COMPLETED) == 0 + && getBootCompletedBroadcastsUidsSize(Intent.ACTION_BOOT_COMPLETED) == 0; + } + } + + /** + * Have less check than {@link #isEmpty()}. + * The dispatcher is considered as idle even with deferred LOCKED_BOOT_COMPLETED/BOOT_COMPLETED + * broadcasts because those can be deferred until the first time the uid's process is started. + * @return + */ + public boolean isIdle() { + synchronized (mLock) { return mCurrentBroadcast == null && mOrderedBroadcasts.isEmpty() && isDeferralsListEmpty(mDeferredBroadcasts) - && isDeferralsListEmpty(mAlarmBroadcasts) - && getBootCompletedBroadcastsUidsSize(Intent.ACTION_LOCKED_BOOT_COMPLETED) == 0 - && getBootCompletedBroadcastsUidsSize(Intent.ACTION_BOOT_COMPLETED) == 0; + && isDeferralsListEmpty(mAlarmBroadcasts); } } diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 0518899fd946..dd7fb84b46bf 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -61,7 +61,6 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; -import android.os.PowerExemptionManager; import android.os.PowerExemptionManager.ReasonCode; import android.os.PowerExemptionManager.TempAllowListType; import android.os.Process; @@ -880,9 +879,9 @@ public final class BroadcastQueue { // Ensure that broadcasts are only sent to other apps if they are explicitly marked as // exported, or are System level broadcasts - if (!skip && !filter.exported && !Process.isCoreUid(r.callingUid) - && filter.receiverList.uid != r.callingUid) { - + if (!skip && !filter.exported && mService.checkComponentPermission(null, r.callingPid, + r.callingUid, filter.receiverList.uid, filter.exported) + != PackageManager.PERMISSION_GRANTED) { Slog.w(TAG, "Exported Denial: sending " + r.intent.toString() + ", action: " + r.intent.getAction() @@ -1934,9 +1933,6 @@ public final class BroadcastQueue { } private void maybeReportBroadcastDispatchedEventLocked(BroadcastRecord r, int targetUid) { - // STOPSHIP (217251579): Temporarily use temp-allowlist reason to identify - // push messages and record response events. - useTemporaryAllowlistReasonAsSignal(r); if (r.options == null || r.options.getIdForResponseEvent() <= 0) { return; } @@ -1951,17 +1947,6 @@ public final class BroadcastQueue { mService.getUidStateLocked(targetUid)); } - private void useTemporaryAllowlistReasonAsSignal(BroadcastRecord r) { - if (r.options == null || r.options.getIdForResponseEvent() > 0) { - return; - } - final int reasonCode = r.options.getTemporaryAppAllowlistReasonCode(); - if (reasonCode == PowerExemptionManager.REASON_PUSH_MESSAGING - || reasonCode == PowerExemptionManager.REASON_PUSH_MESSAGING_OVER_QUOTA) { - r.options.recordResponseEventWhileInBackground(reasonCode); - } - } - @NonNull private UsageStatsManagerInternal getUsageStatsManagerInternal() { final UsageStatsManagerInternal usageStatsManagerInternal = @@ -2233,7 +2218,7 @@ public final class BroadcastQueue { } boolean isIdle() { - return mParallelBroadcasts.isEmpty() && mDispatcher.isEmpty() + return mParallelBroadcasts.isEmpty() && mDispatcher.isIdle() && (mPendingBroadcast == null); } diff --git a/services/core/java/com/android/server/am/ComponentAliasResolver.java b/services/core/java/com/android/server/am/ComponentAliasResolver.java index aef7a6c77b6f..cf910d45b632 100644 --- a/services/core/java/com/android/server/am/ComponentAliasResolver.java +++ b/services/core/java/com/android/server/am/ComponentAliasResolver.java @@ -41,6 +41,7 @@ import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.content.PackageMonitor; import com.android.internal.os.BackgroundThread; +import com.android.server.FgThread; import com.android.server.LocalServices; import com.android.server.compat.CompatChange; import com.android.server.compat.PlatformCompat; @@ -53,17 +54,23 @@ import java.util.function.Supplier; /** * Manages and handles component aliases, which is an experimental feature. * - * For now, this is an experimental feature to evaluate feasibility, so the implementation is + * NOTE: THIS CLASS IS PURELY EXPERIMENTAL AND WILL BE REMOVED IN FUTURE ANDROID VERSIONS. + * DO NOT USE IT. + * + * "Component alias" allows an android manifest component (for now only broadcasts and services) + * to be defined in one android package while having the implementation in a different package. + * + * When/if this becomes a real feature, it will be most likely implemented very differently, + * which is why this shouldn't be used. + * + * For now, because this is an experimental feature to evaluate feasibility, the implementation is * "quick & dirty". For example, to define aliases, we use a regular intent filter and meta-data * in the manifest, instead of adding proper tags/attributes to AndroidManifest.xml. * - * Because it's an experimental feature, it can't be enabled on a user build. + * This feature is disabled by default. * - * Also, for now, aliases can be defined across any packages, but in the final version, there'll - * be restrictions: - * - We probably should only allow either privileged or preinstalled apps. - * - Aliases can only be defined across packages that are atomically installed, and signed with the - * same key. + * Also, for now, aliases can be defined across packages with different certificates, but + * in a final version this will most likely be tightened. */ public class ComponentAliasResolver { private static final String TAG = "ComponentAliasResolver"; @@ -172,12 +179,17 @@ public class ComponentAliasResolver { USE_EXPERIMENTAL_COMPONENT_ALIAS, "android", UserHandle.USER_SYSTEM)); if (enabled != mEnabled) { Slog.i(TAG, (enabled ? "Enabling" : "Disabling") + " component aliases..."); - if (enabled) { - mPackageMonitor.register(mAm.mContext, UserHandle.ALL, - /* externalStorage= */ false, BackgroundThread.getHandler()); - } else { - mPackageMonitor.unregister(); - } + FgThread.getHandler().post(() -> { + // Registering/unregistering a receiver internally takes the AM lock, but AM + // calls into this class while holding the AM lock. So do it on a handler to + // avoid deadlocks. + if (enabled) { + mPackageMonitor.register(mAm.mContext, UserHandle.ALL, + /* externalStorage= */ false, BackgroundThread.getHandler()); + } else { + mPackageMonitor.unregister(); + } + }); } mEnabled = enabled; mEnabledByDeviceConfig = enabledByDeviceConfig; diff --git a/services/core/java/com/android/server/am/PendingTempAllowlists.java b/services/core/java/com/android/server/am/PendingTempAllowlists.java index 0263de7ee586..5d0a347f405f 100644 --- a/services/core/java/com/android/server/am/PendingTempAllowlists.java +++ b/services/core/java/com/android/server/am/PendingTempAllowlists.java @@ -16,8 +16,6 @@ package com.android.server.am; -import static android.os.Process.INVALID_UID; - import android.util.SparseArray; /** Allowlists of uids to temporarily bypass Power Save mode. */ @@ -36,16 +34,12 @@ final class PendingTempAllowlists { synchronized (mPendingTempAllowlist) { mPendingTempAllowlist.put(uid, value); } - mService.mAtmInternal.onUidAddedToPendingTempAllowlist(uid, value.tag); } void removeAt(int index) { - int uid = INVALID_UID; synchronized (mPendingTempAllowlist) { - uid = mPendingTempAllowlist.keyAt(index); mPendingTempAllowlist.removeAt(index); } - mService.mAtmInternal.onUidRemovedFromPendingTempAllowlist(uid); } ActivityManagerService.PendingTempAllowlist get(int uid) { diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index b886196755ea..c04377389e8e 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -173,7 +173,7 @@ class UserController implements Handler.Callback { // Message constant to clear {@link UserJourneySession} from {@link mUserIdToUserJourneyMap} if // the user journey, defined in the UserLifecycleJourneyReported atom for statsd, is not // complete within {@link USER_JOURNEY_TIMEOUT}. - private static final int CLEAR_USER_JOURNEY_SESSION_MSG = 200; + static final int CLEAR_USER_JOURNEY_SESSION_MSG = 200; // Wait time for completing the user journey. If a user journey is not complete within this // time, the remaining lifecycle events for the journey would not be logged in statsd. // Timeout set for 90 seconds. @@ -209,12 +209,15 @@ class UserController implements Handler.Callback { FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_START; private static final int USER_JOURNEY_USER_CREATE = FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_CREATE; + private static final int USER_JOURNEY_USER_STOP = + FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_STOP; @IntDef(prefix = { "USER_JOURNEY" }, value = { USER_JOURNEY_UNKNOWN, USER_JOURNEY_USER_SWITCH_FG, USER_JOURNEY_USER_SWITCH_UI, USER_JOURNEY_USER_START, USER_JOURNEY_USER_CREATE, + USER_JOURNEY_USER_STOP }) @interface UserJourney {} @@ -233,6 +236,8 @@ class UserController implements Handler.Callback { FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__UNLOCKING_USER; private static final int USER_LIFECYCLE_EVENT_UNLOCKED_USER = FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__UNLOCKED_USER; + private static final int USER_LIFECYCLE_EVENT_STOP_USER = + FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__STOP_USER; @IntDef(prefix = { "USER_LIFECYCLE_EVENT" }, value = { USER_LIFECYCLE_EVENT_UNKNOWN, USER_LIFECYCLE_EVENT_SWITCH_USER, @@ -241,6 +246,7 @@ class UserController implements Handler.Callback { USER_LIFECYCLE_EVENT_USER_RUNNING_LOCKED, USER_LIFECYCLE_EVENT_UNLOCKING_USER, USER_LIFECYCLE_EVENT_UNLOCKED_USER, + USER_LIFECYCLE_EVENT_STOP_USER }) @interface UserLifecycleEvent {} @@ -1008,6 +1014,10 @@ class UserController implements Handler.Callback { return; } + logUserJourneyInfo(null, getUserInfo(userId), USER_JOURNEY_USER_STOP); + logUserLifecycleEvent(userId, USER_LIFECYCLE_EVENT_STOP_USER, + USER_LIFECYCLE_EVENT_STATE_BEGIN); + if (stopUserCallback != null) { uss.mStopCallbacks.add(stopUserCallback); } @@ -1066,6 +1076,9 @@ class UserController implements Handler.Callback { synchronized (mLock) { if (uss.state != UserState.STATE_STOPPING) { // Whoops, we are being started back up. Abort, abort! + logUserLifecycleEvent(userId, USER_LIFECYCLE_EVENT_STOP_USER, + USER_LIFECYCLE_EVENT_STATE_NONE); + clearSessionId(userId); return; } uss.setState(UserState.STATE_SHUTDOWN); @@ -1165,10 +1178,18 @@ class UserController implements Handler.Callback { mInjector.getUserManager().removeUserEvenWhenDisallowed(userId); } + logUserLifecycleEvent(userId, USER_LIFECYCLE_EVENT_STOP_USER, + USER_LIFECYCLE_EVENT_STATE_FINISH); + clearSessionId(userId); + if (!lockUser) { return; } dispatchUserLocking(userIdToLock, keyEvictedCallbacks); + } else { + logUserLifecycleEvent(userId, USER_LIFECYCLE_EVENT_STOP_USER, + USER_LIFECYCLE_EVENT_STATE_NONE); + clearSessionId(userId); } } @@ -2962,13 +2983,13 @@ class UserController implements Handler.Callback { if (userJourneySession != null) { // TODO(b/157007231): Move this logic to a separate class/file. if ((userJourneySession.mJourney == USER_JOURNEY_USER_SWITCH_UI - && journey == USER_JOURNEY_USER_START) - || (userJourneySession.mJourney == USER_JOURNEY_USER_SWITCH_FG - && journey == USER_JOURNEY_USER_START)) { + || userJourneySession.mJourney == USER_JOURNEY_USER_SWITCH_FG) + && (journey == USER_JOURNEY_USER_START + || journey == USER_JOURNEY_USER_STOP)) { /* - * There is already a user switch journey, and a user start journey for the same - * target user received. User start journey is most likely a part of user switch - * journey so no need to create a new journey for user start. + * There is already a user switch journey, and a user start or stop journey for + * the same target user received. New journey is most likely a part of user + * switch journey so no need to create a new journey. */ if (DEBUG_MU) { Slogf.d(TAG, journey + " not logged as it is expected to be part of " diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 465e5e9d8453..b1b5d3ffb2c7 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -9712,7 +9712,7 @@ public class AudioService extends IAudioService.Stub //========================================================================================== static final int LOG_NB_EVENTS_LIFECYCLE = 20; static final int LOG_NB_EVENTS_PHONE_STATE = 20; - static final int LOG_NB_EVENTS_DEVICE_CONNECTION = 30; + static final int LOG_NB_EVENTS_DEVICE_CONNECTION = 50; static final int LOG_NB_EVENTS_FORCE_USE = 20; static final int LOG_NB_EVENTS_VOLUME = 40; static final int LOG_NB_EVENTS_DYN_POLICY = 10; diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java b/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java new file mode 100644 index 000000000000..1b24aa896652 --- /dev/null +++ b/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.biometrics.sensors; + +import static android.hardware.biometrics.BiometricStateListener.STATE_AUTH_OTHER; +import static android.hardware.biometrics.BiometricStateListener.STATE_BP_AUTH; +import static android.hardware.biometrics.BiometricStateListener.STATE_ENROLLING; +import static android.hardware.biometrics.BiometricStateListener.STATE_IDLE; +import static android.hardware.biometrics.BiometricStateListener.STATE_KEYGUARD_AUTH; + +import android.annotation.NonNull; +import android.hardware.biometrics.BiometricStateListener; +import android.hardware.biometrics.IBiometricStateListener; +import android.os.RemoteException; +import android.util.Slog; + +import com.android.server.biometrics.Utils; + +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * A callback for receiving notifications about biometric sensor state changes. + */ +public class BiometricStateCallback implements ClientMonitorCallback { + + private static final String TAG = "BiometricStateCallback"; + + @NonNull + private final CopyOnWriteArrayList<IBiometricStateListener> + mBiometricStateListeners = new CopyOnWriteArrayList<>(); + + private @BiometricStateListener.State int mBiometricState; + + public BiometricStateCallback() { + mBiometricState = STATE_IDLE; + } + + public int getBiometricState() { + return mBiometricState; + } + + @Override + public void onClientStarted(@NonNull BaseClientMonitor client) { + final int previousBiometricState = mBiometricState; + + if (client instanceof AuthenticationClient) { + final AuthenticationClient<?> authClient = (AuthenticationClient<?>) client; + if (authClient.isKeyguard()) { + mBiometricState = STATE_KEYGUARD_AUTH; + } else if (authClient.isBiometricPrompt()) { + mBiometricState = STATE_BP_AUTH; + } else { + mBiometricState = STATE_AUTH_OTHER; + } + } else if (client instanceof EnrollClient) { + mBiometricState = STATE_ENROLLING; + } else { + Slog.w(TAG, "Other authentication client: " + Utils.getClientName(client)); + mBiometricState = STATE_IDLE; + } + + Slog.d(TAG, "State updated from " + previousBiometricState + " to " + mBiometricState + + ", client " + client); + notifyBiometricStateListeners(mBiometricState); + } + + @Override + public void onClientFinished(@NonNull BaseClientMonitor client, boolean success) { + mBiometricState = STATE_IDLE; + Slog.d(TAG, "Client finished, state updated to " + mBiometricState + ", client " + + client); + + if (client instanceof EnrollmentModifier) { + EnrollmentModifier enrollmentModifier = (EnrollmentModifier) client; + final boolean enrollmentStateChanged = enrollmentModifier.hasEnrollmentStateChanged(); + Slog.d(TAG, "Enrollment state changed: " + enrollmentStateChanged); + if (enrollmentStateChanged) { + notifyAllEnrollmentStateChanged(client.getTargetUserId(), + client.getSensorId(), + enrollmentModifier.hasEnrollments()); + } + } + + notifyBiometricStateListeners(mBiometricState); + } + + private void notifyBiometricStateListeners(@BiometricStateListener.State int newState) { + for (IBiometricStateListener listener : mBiometricStateListeners) { + try { + listener.onStateChanged(newState); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception in biometric state change", e); + } + } + } + + /** + * This should be invoked when: + * 1) Enrolled --> None-enrolled + * 2) None-enrolled --> enrolled + * 3) HAL becomes ready + * 4) Listener is registered + */ + public void notifyAllEnrollmentStateChanged(int userId, int sensorId, + boolean hasEnrollments) { + for (IBiometricStateListener listener : mBiometricStateListeners) { + notifyEnrollmentStateChanged(listener, userId, sensorId, hasEnrollments); + } + } + + /** + * Notifies the listener of enrollment state changes. + */ + public void notifyEnrollmentStateChanged(@NonNull IBiometricStateListener listener, + int userId, int sensorId, boolean hasEnrollments) { + try { + listener.onEnrollmentsChanged(userId, sensorId, hasEnrollments); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception", e); + } + } + + /** + * Enables clients to register a BiometricStateListener. For example, this is used to forward + * fingerprint sensor state changes to SideFpsEventHandler. + * + * @param listener + */ + public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) { + mBiometricStateListeners.add(listener); + } +} diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java index 5727ffc468df..97efc7813230 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java @@ -42,6 +42,7 @@ import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.IBiometricSensorReceiver; import android.hardware.biometrics.IBiometricService; import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; +import android.hardware.biometrics.IBiometricStateListener; import android.hardware.biometrics.IInvalidationCallback; import android.hardware.biometrics.ITestSession; import android.hardware.biometrics.ITestSessionCallback; @@ -55,7 +56,6 @@ import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback import android.hardware.fingerprint.IFingerprintClientActiveCallback; import android.hardware.fingerprint.IFingerprintService; import android.hardware.fingerprint.IFingerprintServiceReceiver; -import android.hardware.fingerprint.IFingerprintStateListener; import android.hardware.fingerprint.ISidefpsController; import android.hardware.fingerprint.IUdfpsOverlayController; import android.os.Binder; @@ -84,6 +84,7 @@ import com.android.server.ServiceThread; import com.android.server.SystemService; import com.android.server.biometrics.Utils; import com.android.server.biometrics.log.BiometricContext; +import com.android.server.biometrics.sensors.BiometricStateCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.LockoutResetDispatcher; import com.android.server.biometrics.sensors.LockoutTracker; @@ -114,7 +115,7 @@ public class FingerprintService extends SystemService { private final LockPatternUtils mLockPatternUtils; private final FingerprintServiceWrapper mServiceWrapper; @NonNull private final List<ServiceProvider> mServiceProviders; - @NonNull private final FingerprintStateCallback mFingerprintStateCallback; + @NonNull private final BiometricStateCallback mBiometricStateCallback; @NonNull private final Handler mHandler; @GuardedBy("mLock") @@ -125,20 +126,20 @@ public class FingerprintService extends SystemService { @NonNull private final List<FingerprintSensorPropertiesInternal> mSensorProps; /** - * Registers FingerprintStateListener in list stored by FingerprintService - * @param listener new FingerprintStateListener being added + * Registers BiometricStateListener in list stored by FingerprintService + * @param listener new BiometricStateListener being added */ - public void registerFingerprintStateListener(@NonNull IFingerprintStateListener listener) { - mFingerprintStateCallback.registerFingerprintStateListener(listener); + public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) { + mBiometricStateCallback.registerBiometricStateListener(listener); broadcastCurrentEnrollmentState(listener); } /** * @param listener if non-null, notifies only this listener. if null, notifies all listeners - * in {@link FingerprintStateCallback}. This is slightly ugly, but reduces + * in {@link BiometricStateCallback}. This is slightly ugly, but reduces * redundant code. */ - private void broadcastCurrentEnrollmentState(@Nullable IFingerprintStateListener listener) { + private void broadcastCurrentEnrollmentState(@Nullable IBiometricStateListener listener) { final UserManager um = UserManager.get(getContext()); synchronized (mLock) { // Update the new listener with current state of all sensors @@ -151,10 +152,10 @@ public class FingerprintService extends SystemService { // Defer this work and allow the loop to release the lock sooner mHandler.post(() -> { if (listener != null) { - mFingerprintStateCallback.notifyFingerprintEnrollmentStateChanged( + mBiometricStateCallback.notifyEnrollmentStateChanged( listener, userInfo.id, prop.sensorId, enrolled); } else { - mFingerprintStateCallback.notifyAllFingerprintEnrollmentStateChanged( + mBiometricStateCallback.notifyAllEnrollmentStateChanged( userInfo.id, prop.sensorId, enrolled); } }); @@ -651,7 +652,7 @@ public class FingerprintService extends SystemService { pw.println("Dumping for sensorId: " + props.sensorId + ", provider: " + provider.getClass().getSimpleName()); pw.println("Fps state: " - + mFingerprintStateCallback.getFingerprintState()); + + mBiometricStateCallback.getBiometricState()); provider.dumpInternal(props.sensorId, pw); pw.println(); } @@ -847,12 +848,12 @@ public class FingerprintService extends SystemService { Fingerprint21UdfpsMock.CONFIG_ENABLE_TEST_UDFPS, 0 /* default */, UserHandle.USER_CURRENT) != 0) { fingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(), - mFingerprintStateCallback, hidlSensor, + mBiometricStateCallback, hidlSensor, mLockoutResetDispatcher, mGestureAvailabilityDispatcher, BiometricContext.getInstance(getContext())); } else { fingerprint21 = Fingerprint21.newInstance(getContext(), - mFingerprintStateCallback, hidlSensor, mHandler, + mBiometricStateCallback, hidlSensor, mHandler, mLockoutResetDispatcher, mGestureAvailabilityDispatcher); } mServiceProviders.add(fingerprint21); @@ -875,7 +876,7 @@ public class FingerprintService extends SystemService { try { final SensorProps[] props = fp.getSensorProps(); final FingerprintProvider provider = - new FingerprintProvider(getContext(), mFingerprintStateCallback, props, + new FingerprintProvider(getContext(), mBiometricStateCallback, props, instance, mLockoutResetDispatcher, mGestureAvailabilityDispatcher, BiometricContext.getInstance(getContext())); @@ -1015,8 +1016,8 @@ public class FingerprintService extends SystemService { } @Override - public void registerFingerprintStateListener(@NonNull IFingerprintStateListener listener) { - FingerprintService.this.registerFingerprintStateListener(listener); + public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) { + FingerprintService.this.registerBiometricStateListener(listener); } } @@ -1028,7 +1029,7 @@ public class FingerprintService extends SystemService { mLockoutResetDispatcher = new LockoutResetDispatcher(context); mLockPatternUtils = new LockPatternUtils(context); mServiceProviders = new ArrayList<>(); - mFingerprintStateCallback = new FingerprintStateCallback(); + mBiometricStateCallback = new BiometricStateCallback(); mAuthenticatorsRegisteredCallbacks = new RemoteCallbackList<>(); mSensorProps = new ArrayList<>(); mHandler = new Handler(Looper.getMainLooper()); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java deleted file mode 100644 index 04fd534adb3b..000000000000 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.biometrics.sensors.fingerprint; - -import static android.hardware.fingerprint.FingerprintStateListener.STATE_AUTH_OTHER; -import static android.hardware.fingerprint.FingerprintStateListener.STATE_BP_AUTH; -import static android.hardware.fingerprint.FingerprintStateListener.STATE_ENROLLING; -import static android.hardware.fingerprint.FingerprintStateListener.STATE_IDLE; -import static android.hardware.fingerprint.FingerprintStateListener.STATE_KEYGUARD_AUTH; - -import android.annotation.NonNull; -import android.hardware.fingerprint.FingerprintStateListener; -import android.hardware.fingerprint.IFingerprintStateListener; -import android.os.RemoteException; -import android.util.Slog; - -import com.android.server.biometrics.Utils; -import com.android.server.biometrics.sensors.AuthenticationClient; -import com.android.server.biometrics.sensors.BaseClientMonitor; -import com.android.server.biometrics.sensors.ClientMonitorCallback; -import com.android.server.biometrics.sensors.EnrollClient; -import com.android.server.biometrics.sensors.EnrollmentModifier; - -import java.util.concurrent.CopyOnWriteArrayList; - -/** - * A callback for receiving notifications about changes in fingerprint state. - */ -public class FingerprintStateCallback implements ClientMonitorCallback { - - @NonNull private final CopyOnWriteArrayList<IFingerprintStateListener> - mFingerprintStateListeners = new CopyOnWriteArrayList<>(); - - private @FingerprintStateListener.State int mFingerprintState; - - public FingerprintStateCallback() { - mFingerprintState = STATE_IDLE; - } - - public int getFingerprintState() { - return mFingerprintState; - } - - @Override - public void onClientStarted(@NonNull BaseClientMonitor client) { - final int previousFingerprintState = mFingerprintState; - - if (client instanceof AuthenticationClient) { - final AuthenticationClient<?> authClient = (AuthenticationClient<?>) client; - if (authClient.isKeyguard()) { - mFingerprintState = STATE_KEYGUARD_AUTH; - } else if (authClient.isBiometricPrompt()) { - mFingerprintState = STATE_BP_AUTH; - } else { - mFingerprintState = STATE_AUTH_OTHER; - } - } else if (client instanceof EnrollClient) { - mFingerprintState = STATE_ENROLLING; - } else { - Slog.w(FingerprintService.TAG, - "Other authentication client: " + Utils.getClientName(client)); - mFingerprintState = STATE_IDLE; - } - - Slog.d(FingerprintService.TAG, "Fps state updated from " + previousFingerprintState - + " to " + mFingerprintState + ", client " + client); - notifyFingerprintStateListeners(mFingerprintState); - } - - @Override - public void onClientFinished(@NonNull BaseClientMonitor client, boolean success) { - mFingerprintState = STATE_IDLE; - Slog.d(FingerprintService.TAG, - "Client finished, fps state updated to " + mFingerprintState + ", client " - + client); - - if (client instanceof EnrollmentModifier) { - EnrollmentModifier enrollmentModifier = (EnrollmentModifier) client; - final boolean enrollmentStateChanged = enrollmentModifier.hasEnrollmentStateChanged(); - Slog.d(FingerprintService.TAG, "Enrollment state changed: " + enrollmentStateChanged); - if (enrollmentStateChanged) { - notifyAllFingerprintEnrollmentStateChanged(client.getTargetUserId(), - client.getSensorId(), - enrollmentModifier.hasEnrollments()); - } - } - - notifyFingerprintStateListeners(mFingerprintState); - } - - private void notifyFingerprintStateListeners(@FingerprintStateListener.State int newState) { - for (IFingerprintStateListener listener : mFingerprintStateListeners) { - try { - listener.onStateChanged(newState); - } catch (RemoteException e) { - Slog.e(FingerprintService.TAG, "Remote exception in fingerprint state change", e); - } - } - } - - /** - * This should be invoked when: - * 1) Enrolled --> None-enrolled - * 2) None-enrolled --> enrolled - * 3) HAL becomes ready - * 4) Listener is registered - */ - void notifyAllFingerprintEnrollmentStateChanged(int userId, int sensorId, - boolean hasEnrollments) { - for (IFingerprintStateListener listener : mFingerprintStateListeners) { - notifyFingerprintEnrollmentStateChanged(listener, userId, sensorId, hasEnrollments); - } - } - - /** - * Notifies the listener of enrollment state changes. - */ - void notifyFingerprintEnrollmentStateChanged(@NonNull IFingerprintStateListener listener, - int userId, int sensorId, boolean hasEnrollments) { - try { - listener.onEnrollmentsChanged(userId, sensorId, hasEnrollments); - } catch (RemoteException e) { - Slog.e(FingerprintService.TAG, "Remote exception", e); - } - } - - /** - * Enables clients to register a FingerprintStateListener. Used by FingerprintService to forward - * updates in fingerprint sensor state to the SideFpNsEventHandler - * - * @param listener - */ - public void registerFingerprintStateListener(@NonNull IFingerprintStateListener listener) { - mFingerprintStateListeners.add(listener); - } -} diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java index 0528cd489ae5..ba7202fec93b 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java @@ -32,8 +32,8 @@ import android.util.Slog; import com.android.server.biometrics.HardwareAuthTokenUtils; import com.android.server.biometrics.Utils; import com.android.server.biometrics.sensors.BaseClientMonitor; +import com.android.server.biometrics.sensors.BiometricStateCallback; import com.android.server.biometrics.sensors.ClientMonitorCallback; -import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback; import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils; import java.util.HashSet; @@ -52,7 +52,7 @@ class BiometricTestSessionImpl extends ITestSession.Stub { @NonNull private final Context mContext; private final int mSensorId; @NonNull private final ITestSessionCallback mCallback; - @NonNull private final FingerprintStateCallback mFingerprintStateCallback; + @NonNull private final BiometricStateCallback mBiometricStateCallback; @NonNull private final FingerprintProvider mProvider; @NonNull private final Sensor mSensor; @NonNull private final Set<Integer> mEnrollmentIds; @@ -118,13 +118,13 @@ class BiometricTestSessionImpl extends ITestSession.Stub { BiometricTestSessionImpl(@NonNull Context context, int sensorId, @NonNull ITestSessionCallback callback, - @NonNull FingerprintStateCallback fingerprintStateCallback, + @NonNull BiometricStateCallback biometricStateCallback, @NonNull FingerprintProvider provider, @NonNull Sensor sensor) { mContext = context; mSensorId = sensorId; mCallback = callback; - mFingerprintStateCallback = fingerprintStateCallback; + mBiometricStateCallback = biometricStateCallback; mProvider = provider; mSensor = sensor; mEnrollmentIds = new HashSet<>(); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java index 1fac8a8ce5c9..7d5b77c2d711 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java @@ -58,13 +58,13 @@ import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.log.BiometricLogger; import com.android.server.biometrics.sensors.AuthenticationClient; import com.android.server.biometrics.sensors.BaseClientMonitor; +import com.android.server.biometrics.sensors.BiometricStateCallback; import com.android.server.biometrics.sensors.ClientMonitorCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback; import com.android.server.biometrics.sensors.InvalidationRequesterClient; import com.android.server.biometrics.sensors.LockoutResetDispatcher; import com.android.server.biometrics.sensors.PerformanceTracker; -import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback; import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils; import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher; import com.android.server.biometrics.sensors.fingerprint.ServiceProvider; @@ -91,7 +91,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi private boolean mTestHalEnabled; @NonNull private final Context mContext; - @NonNull private final FingerprintStateCallback mFingerprintStateCallback; + @NonNull private final BiometricStateCallback mBiometricStateCallback; @NonNull private final String mHalInstanceName; @NonNull @VisibleForTesting final SparseArray<Sensor> mSensors; // Map of sensors that this HAL supports @@ -141,13 +141,13 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi } public FingerprintProvider(@NonNull Context context, - @NonNull FingerprintStateCallback fingerprintStateCallback, + @NonNull BiometricStateCallback biometricStateCallback, @NonNull SensorProps[] props, @NonNull String halInstanceName, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher, @NonNull BiometricContext biometricContext) { mContext = context; - mFingerprintStateCallback = fingerprintStateCallback; + mBiometricStateCallback = biometricStateCallback; mHalInstanceName = halInstanceName; mSensors = new SparseArray<>(); mHandler = new Handler(Looper.getMainLooper()); @@ -389,13 +389,13 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @Override public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) { - mFingerprintStateCallback.onClientStarted(clientMonitor); + mBiometricStateCallback.onClientStarted(clientMonitor); } @Override public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) { - mFingerprintStateCallback.onClientFinished(clientMonitor, success); + mBiometricStateCallback.onClientFinished(clientMonitor, success); if (success) { scheduleLoadAuthenticatorIdsForUser(sensorId, userId); scheduleInvalidationRequest(sensorId, userId); @@ -425,7 +425,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient), mBiometricContext, mUdfpsOverlayController, isStrongBiometric); - scheduleForSensor(sensorId, client, mFingerprintStateCallback); + scheduleForSensor(sensorId, client, mBiometricStateCallback); }); return id; @@ -447,7 +447,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi mTaskStackListener, mSensors.get(sensorId).getLockoutCache(), mUdfpsOverlayController, mSidefpsController, allowBackgroundAuthentication, mSensors.get(sensorId).getSensorProperties()); - scheduleForSensor(sensorId, client, mFingerprintStateCallback); + scheduleForSensor(sensorId, client, mBiometricStateCallback); }); } @@ -509,7 +509,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi BiometricsProtoEnums.CLIENT_UNKNOWN), mBiometricContext, mSensors.get(sensorId).getAuthenticatorIds()); - scheduleForSensor(sensorId, client, mFingerprintStateCallback); + scheduleForSensor(sensorId, client, mBiometricStateCallback); }); } @@ -528,7 +528,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi enrolledList, FingerprintUtils.getInstance(sensorId), mSensors.get(sensorId).getAuthenticatorIds()); scheduleForSensor(sensorId, client, new ClientMonitorCompositeCallback(callback, - mFingerprintStateCallback)); + mBiometricStateCallback)); }); } @@ -680,7 +680,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @Override public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback, @NonNull String opPackageName) { - return mSensors.get(sensorId).createTestSession(callback, mFingerprintStateCallback); + return mSensors.get(sensorId).createTestSession(callback, mBiometricStateCallback); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java index 024d611732c1..1dcf4e9528d2 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java @@ -55,6 +55,7 @@ import com.android.server.biometrics.sensors.AcquisitionClient; import com.android.server.biometrics.sensors.AuthenticationConsumer; import com.android.server.biometrics.sensors.BaseClientMonitor; import com.android.server.biometrics.sensors.BiometricScheduler; +import com.android.server.biometrics.sensors.BiometricStateCallback; import com.android.server.biometrics.sensors.EnumerateConsumer; import com.android.server.biometrics.sensors.ErrorConsumer; import com.android.server.biometrics.sensors.LockoutCache; @@ -64,7 +65,6 @@ import com.android.server.biometrics.sensors.RemovalConsumer; import com.android.server.biometrics.sensors.StartUserClient; import com.android.server.biometrics.sensors.StopUserClient; import com.android.server.biometrics.sensors.UserAwareBiometricScheduler; -import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback; import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils; import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher; @@ -527,9 +527,9 @@ public class Sensor { } @NonNull ITestSession createTestSession(@NonNull ITestSessionCallback callback, - @NonNull FingerprintStateCallback fingerprintStateCallback) { + @NonNull BiometricStateCallback biometricStateCallback) { return new BiometricTestSessionImpl(mContext, mSensorProperties.sensorId, callback, - fingerprintStateCallback, mProvider, this); + biometricStateCallback, mProvider, this); } @NonNull BiometricScheduler getScheduler() { diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java index 033855f822a4..a58bb8981cf6 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java @@ -31,8 +31,8 @@ import android.util.Slog; import com.android.server.biometrics.Utils; import com.android.server.biometrics.sensors.BaseClientMonitor; +import com.android.server.biometrics.sensors.BiometricStateCallback; import com.android.server.biometrics.sensors.ClientMonitorCallback; -import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback; import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils; import java.util.ArrayList; @@ -53,7 +53,7 @@ public class BiometricTestSessionImpl extends ITestSession.Stub { @NonNull private final Context mContext; private final int mSensorId; @NonNull private final ITestSessionCallback mCallback; - @NonNull private final FingerprintStateCallback mFingerprintStateCallback; + @NonNull private final BiometricStateCallback mBiometricStateCallback; @NonNull private final Fingerprint21 mFingerprint21; @NonNull private final Fingerprint21.HalResultController mHalResultController; @NonNull private final Set<Integer> mEnrollmentIds; @@ -119,14 +119,14 @@ public class BiometricTestSessionImpl extends ITestSession.Stub { BiometricTestSessionImpl(@NonNull Context context, int sensorId, @NonNull ITestSessionCallback callback, - @NonNull FingerprintStateCallback fingerprintStateCallback, + @NonNull BiometricStateCallback biometricStateCallback, @NonNull Fingerprint21 fingerprint21, @NonNull Fingerprint21.HalResultController halResultController) { mContext = context; mSensorId = sensorId; mCallback = callback; mFingerprint21 = fingerprint21; - mFingerprintStateCallback = fingerprintStateCallback; + mBiometricStateCallback = biometricStateCallback; mHalResultController = halResultController; mEnrollmentIds = new HashSet<>(); mRandom = new Random(); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java index 1d2a3655021c..52dbe2460e1c 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java @@ -64,6 +64,7 @@ import com.android.server.biometrics.sensors.AuthenticationClient; import com.android.server.biometrics.sensors.AuthenticationConsumer; import com.android.server.biometrics.sensors.BaseClientMonitor; import com.android.server.biometrics.sensors.BiometricScheduler; +import com.android.server.biometrics.sensors.BiometricStateCallback; import com.android.server.biometrics.sensors.ClientMonitorCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback; @@ -73,7 +74,6 @@ import com.android.server.biometrics.sensors.LockoutResetDispatcher; import com.android.server.biometrics.sensors.LockoutTracker; import com.android.server.biometrics.sensors.PerformanceTracker; import com.android.server.biometrics.sensors.RemovalConsumer; -import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback; import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils; import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher; import com.android.server.biometrics.sensors.fingerprint.ServiceProvider; @@ -105,7 +105,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider private boolean mTestHalEnabled; final Context mContext; - @NonNull private final FingerprintStateCallback mFingerprintStateCallback; + @NonNull private final BiometricStateCallback mBiometricStateCallback; private final ActivityTaskManager mActivityTaskManager; @NonNull private final FingerprintSensorPropertiesInternal mSensorProperties; private final BiometricScheduler mScheduler; @@ -323,7 +323,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider @VisibleForTesting Fingerprint21(@NonNull Context context, - @NonNull FingerprintStateCallback fingerprintStateCallback, + @NonNull BiometricStateCallback biometricStateCallback, @NonNull FingerprintSensorPropertiesInternal sensorProps, @NonNull BiometricScheduler scheduler, @NonNull Handler handler, @@ -331,7 +331,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider @NonNull HalResultController controller, @NonNull BiometricContext biometricContext) { mContext = context; - mFingerprintStateCallback = fingerprintStateCallback; + mBiometricStateCallback = biometricStateCallback; mBiometricContext = biometricContext; mSensorProperties = sensorProps; @@ -362,7 +362,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider } public static Fingerprint21 newInstance(@NonNull Context context, - @NonNull FingerprintStateCallback fingerprintStateCallback, + @NonNull BiometricStateCallback biometricStateCallback, @NonNull FingerprintSensorPropertiesInternal sensorProps, @NonNull Handler handler, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @@ -373,7 +373,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider gestureAvailabilityDispatcher); final HalResultController controller = new HalResultController(sensorProps.sensorId, context, handler, scheduler); - return new Fingerprint21(context, fingerprintStateCallback, sensorProps, scheduler, handler, + return new Fingerprint21(context, biometricStateCallback, sensorProps, scheduler, handler, lockoutResetDispatcher, controller, BiometricContext.getInstance(context)); } @@ -604,13 +604,13 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() { @Override public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) { - mFingerprintStateCallback.onClientStarted(clientMonitor); + mBiometricStateCallback.onClientStarted(clientMonitor); } @Override public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) { - mFingerprintStateCallback.onClientFinished(clientMonitor, success); + mBiometricStateCallback.onClientFinished(clientMonitor, success); if (success) { // Update authenticatorIds scheduleUpdateActiveUserWithoutHandler(clientMonitor.getTargetUserId(), @@ -642,7 +642,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient), mBiometricContext, mUdfpsOverlayController, isStrongBiometric); - mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback); + mScheduler.scheduleClientMonitor(client, mBiometricStateCallback); }); return id; @@ -666,7 +666,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider mTaskStackListener, mLockoutTracker, mUdfpsOverlayController, mSidefpsController, allowBackgroundAuthentication, mSensorProperties); - mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback); + mScheduler.scheduleClientMonitor(client, mBiometricStateCallback); }); } @@ -708,7 +708,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider createLogger(BiometricsProtoEnums.ACTION_REMOVE, BiometricsProtoEnums.CLIENT_UNKNOWN), mBiometricContext, mAuthenticatorIds); - mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback); + mScheduler.scheduleClientMonitor(client, mBiometricStateCallback); }); } @@ -728,7 +728,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider createLogger(BiometricsProtoEnums.ACTION_REMOVE, BiometricsProtoEnums.CLIENT_UNKNOWN), mBiometricContext, mAuthenticatorIds); - mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback); + mScheduler.scheduleClientMonitor(client, mBiometricStateCallback); }); } @@ -754,7 +754,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider public void scheduleInternalCleanup(int sensorId, int userId, @Nullable ClientMonitorCallback callback) { scheduleInternalCleanup(userId, new ClientMonitorCompositeCallback(callback, - mFingerprintStateCallback)); + mBiometricStateCallback)); } private BiometricLogger createLogger(int statsAction, int statsClient) { @@ -967,6 +967,6 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback, @NonNull String opPackageName) { return new BiometricTestSessionImpl(mContext, mSensorProperties.sensorId, callback, - mFingerprintStateCallback, this, mHalResultController); + mBiometricStateCallback, this, mHalResultController); } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java index a4e343e786c1..485a674dda92 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java @@ -41,9 +41,9 @@ import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.sensors.AuthenticationConsumer; import com.android.server.biometrics.sensors.BaseClientMonitor; import com.android.server.biometrics.sensors.BiometricScheduler; +import com.android.server.biometrics.sensors.BiometricStateCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.LockoutResetDispatcher; -import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback; import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher; import java.util.ArrayList; @@ -245,7 +245,7 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage } public static Fingerprint21UdfpsMock newInstance(@NonNull Context context, - @NonNull FingerprintStateCallback fingerprintStateCallback, + @NonNull BiometricStateCallback biometricStateCallback, @NonNull FingerprintSensorPropertiesInternal sensorProps, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher, @@ -257,7 +257,7 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage new TestableBiometricScheduler(TAG, handler, gestureAvailabilityDispatcher); final MockHalResultController controller = new MockHalResultController(sensorProps.sensorId, context, handler, scheduler); - return new Fingerprint21UdfpsMock(context, fingerprintStateCallback, sensorProps, scheduler, + return new Fingerprint21UdfpsMock(context, biometricStateCallback, sensorProps, scheduler, handler, lockoutResetDispatcher, controller, biometricContext); } @@ -382,14 +382,14 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage } private Fingerprint21UdfpsMock(@NonNull Context context, - @NonNull FingerprintStateCallback fingerprintStateCallback, + @NonNull BiometricStateCallback biometricStateCallback, @NonNull FingerprintSensorPropertiesInternal sensorProps, @NonNull TestableBiometricScheduler scheduler, @NonNull Handler handler, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull MockHalResultController controller, @NonNull BiometricContext biometricContext) { - super(context, fingerprintStateCallback, sensorProps, scheduler, handler, + super(context, biometricStateCallback, sensorProps, scheduler, handler, lockoutResetDispatcher, controller, biometricContext); mScheduler = scheduler; mScheduler.init(this); diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java index 7db99f1da130..be112537274a 100644 --- a/services/core/java/com/android/server/camera/CameraServiceProxy.java +++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java @@ -239,6 +239,8 @@ public class CameraServiceProxy extends SystemService public long mResultErrorCount; public boolean mDeviceError; public List<CameraStreamStats> mStreamStats; + public String mUserTag; + private long mDurationOrStartTimeMs; // Either start time, or duration once completed CameraUsageEvent(String cameraId, int facing, String clientName, int apiLevel, @@ -257,7 +259,7 @@ public class CameraServiceProxy extends SystemService public void markCompleted(int internalReconfigure, long requestCount, long resultErrorCount, boolean deviceError, - List<CameraStreamStats> streamStats) { + List<CameraStreamStats> streamStats, String userTag) { if (mCompleted) { return; } @@ -268,6 +270,7 @@ public class CameraServiceProxy extends SystemService mResultErrorCount = resultErrorCount; mDeviceError = deviceError; mStreamStats = streamStats; + mUserTag = userTag; if (CameraServiceProxy.DEBUG) { Slog.v(TAG, "A camera facing " + cameraFacingToString(mCameraFacing) + " was in use by " + mClientName + " for " + @@ -794,7 +797,8 @@ public class CameraServiceProxy extends SystemService + ", requestCount " + e.mRequestCount + ", resultErrorCount " + e.mResultErrorCount + ", deviceError " + e.mDeviceError - + ", streamCount is " + streamCount); + + ", streamCount is " + streamCount + + ", userTag is " + e.mUserTag); } // Convert from CameraStreamStats to CameraStreamProto CameraStreamProto[] streamProtos = new CameraStreamProto[MAX_STREAM_STATISTICS]; @@ -851,7 +855,8 @@ public class CameraServiceProxy extends SystemService MessageNano.toByteArray(streamProtos[1]), MessageNano.toByteArray(streamProtos[2]), MessageNano.toByteArray(streamProtos[3]), - MessageNano.toByteArray(streamProtos[4])); + MessageNano.toByteArray(streamProtos[4]), + e.mUserTag); } } @@ -1038,6 +1043,7 @@ public class CameraServiceProxy extends SystemService long resultErrorCount = cameraState.getResultErrorCount(); boolean deviceError = cameraState.getDeviceErrorFlag(); List<CameraStreamStats> streamStats = cameraState.getStreamStats(); + String userTag = cameraState.getUserTag(); synchronized(mLock) { // Update active camera list and notify NFC if necessary boolean wasEmpty = mActiveCameraUsage.isEmpty(); @@ -1091,7 +1097,8 @@ public class CameraServiceProxy extends SystemService if (oldEvent != null) { Slog.w(TAG, "Camera " + cameraId + " was already marked as active"); oldEvent.markCompleted(/*internalReconfigure*/0, /*requestCount*/0, - /*resultErrorCount*/0, /*deviceError*/false, streamStats); + /*resultErrorCount*/0, /*deviceError*/false, streamStats, + /*userTag*/""); mCameraUsageHistory.add(oldEvent); } break; @@ -1101,7 +1108,7 @@ public class CameraServiceProxy extends SystemService if (doneEvent != null) { doneEvent.markCompleted(internalReconfigureCount, requestCount, - resultErrorCount, deviceError, streamStats); + resultErrorCount, deviceError, streamStats, userTag); mCameraUsageHistory.add(doneEvent); // Check current active camera IDs to see if this package is still diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java index 9f46bd6cf28a..3f002449c1eb 100644 --- a/services/core/java/com/android/server/clipboard/ClipboardService.java +++ b/services/core/java/com/android/server/clipboard/ClipboardService.java @@ -665,7 +665,7 @@ public class ClipboardService extends SystemService { void setPrimaryClipInternal(PerUserClipboard clipboard, @Nullable ClipData clip, int uid) { - synchronized ("mLock") { + synchronized (mLock) { setPrimaryClipInternalLocked(clipboard, clip, uid, null); } } diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 4c9b28b1bd18..d9e4828e7eb4 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -20,6 +20,7 @@ import static android.Manifest.permission.BIND_VPN_SERVICE; import static android.Manifest.permission.CONTROL_VPN; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; import static android.net.RouteInfo.RTN_THROW; import static android.net.RouteInfo.RTN_UNREACHABLE; import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN; @@ -2549,6 +2550,7 @@ public class Vpn { req = new NetworkRequest.Builder() .clearCapabilities() .addTransportType(NetworkCapabilities.TRANSPORT_TEST) + .addCapability(NET_CAPABILITY_NOT_VPN) .build(); } else { // Basically, the request here is referring to the default request which is defined diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index a155095c0725..982ac3c84482 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -76,6 +76,8 @@ final class LocalDisplayAdapter extends DisplayAdapter { private final boolean mIsBootDisplayModeSupported; + private Context mOverlayContext; + // Called with SyncRoot lock held. public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, Context context, Handler handler, Listener listener) { @@ -1222,7 +1224,10 @@ final class LocalDisplayAdapter extends DisplayAdapter { /** Supplies a context whose Resources apply runtime-overlays */ Context getOverlayContext() { - return ActivityThread.currentActivityThread().getSystemUiContext(); + if (mOverlayContext == null) { + mOverlayContext = ActivityThread.currentActivityThread().getSystemUiContext(); + } + return mOverlayContext; } /** diff --git a/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java b/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java index 1c296e5b5640..8647680e52a6 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java @@ -83,7 +83,9 @@ public final class HdmiCecStandbyModeHandler { private final HdmiCecLocalDevice mDevice; private final SparseArray<CecMessageHandler> mCecMessageHandlers = new SparseArray<>(); - private final CecMessageHandler mDefaultHandler = new Aborter( + private final CecMessageHandler mDefaultHandler; + + private final CecMessageHandler mAborterUnrecognizedOpcode = new Aborter( Constants.ABORT_UNRECOGNIZED_OPCODE); private final CecMessageHandler mAborterIncorrectMode = new Aborter( Constants.ABORT_NOT_IN_CORRECT_MODE); @@ -95,6 +97,10 @@ public final class HdmiCecStandbyModeHandler { mUserControlProcessedHandler = new UserControlProcessedHandler(); private void addCommonHandlers() { + addHandler(Constants.MESSAGE_USER_CONTROL_PRESSED, mUserControlProcessedHandler); + } + + private void addTvHandlers() { addHandler(Constants.MESSAGE_ACTIVE_SOURCE, mBystander); addHandler(Constants.MESSAGE_REQUEST_ACTIVE_SOURCE, mBystander); addHandler(Constants.MESSAGE_ROUTING_CHANGE, mBystander); @@ -118,17 +124,13 @@ public final class HdmiCecStandbyModeHandler { addHandler(Constants.MESSAGE_REPORT_POWER_STATUS, mBypasser); addHandler(Constants.MESSAGE_GIVE_FEATURES, mBypasser); - addHandler(Constants.MESSAGE_USER_CONTROL_PRESSED, mUserControlProcessedHandler); - addHandler(Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS, mBypasser); addHandler(Constants.MESSAGE_ABORT, mBypasser); addHandler(Constants.MESSAGE_GET_CEC_VERSION, mBypasser); addHandler(Constants.MESSAGE_VENDOR_COMMAND_WITH_ID, mAborterIncorrectMode); addHandler(Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE, mAborterIncorrectMode); - } - private void addTvHandlers() { addHandler(Constants.MESSAGE_IMAGE_VIEW_ON, mAutoOnHandler); addHandler(Constants.MESSAGE_TEXT_VIEW_ON, mAutoOnHandler); @@ -153,6 +155,9 @@ public final class HdmiCecStandbyModeHandler { addCommonHandlers(); if (mDevice.getType() == HdmiDeviceInfo.DEVICE_TV) { addTvHandlers(); + mDefaultHandler = mAborterUnrecognizedOpcode; + } else { + mDefaultHandler = mBypasser; } } diff --git a/services/core/java/com/android/server/health/HealthRegCallbackAidl.java b/services/core/java/com/android/server/health/HealthRegCallbackAidl.java index 629011a86bb4..90a2f480643d 100644 --- a/services/core/java/com/android/server/health/HealthRegCallbackAidl.java +++ b/services/core/java/com/android/server/health/HealthRegCallbackAidl.java @@ -115,5 +115,13 @@ public class HealthRegCallbackAidl { public void healthInfoChanged(HealthInfo healthInfo) throws RemoteException { mServiceInfoCallback.update(healthInfo); } + @Override + public String getInterfaceHash() { + return IHealthInfoCallback.HASH; + } + @Override + public int getInterfaceVersion() { + return IHealthInfoCallback.VERSION; + } } } diff --git a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java index a1ee46b4c943..acc0746764c5 100644 --- a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java +++ b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java @@ -389,6 +389,15 @@ public abstract class IContextHubWrapper { mCallback.handleTransactionResult(transactionId, success); }); } + @Override + public String getInterfaceHash() { + return android.hardware.contexthub.IContextHubCallback.HASH; + } + + @Override + public int getInterfaceVersion() { + return android.hardware.contexthub.IContextHubCallback.VERSION; + } } ContextHubWrapperAidl(android.hardware.contexthub.IContextHub hub) { diff --git a/services/core/java/com/android/server/location/gnss/GnssConfiguration.java b/services/core/java/com/android/server/location/gnss/GnssConfiguration.java index 5fe77109eea3..12f8776a8e18 100644 --- a/services/core/java/com/android/server/location/gnss/GnssConfiguration.java +++ b/services/core/java/com/android/server/location/gnss/GnssConfiguration.java @@ -70,9 +70,14 @@ public class GnssConfiguration { "USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL"; private static final String CONFIG_GPS_LOCK = "GPS_LOCK"; private static final String CONFIG_ES_EXTENSION_SEC = "ES_EXTENSION_SEC"; - public static final String CONFIG_NFW_PROXY_APPS = "NFW_PROXY_APPS"; - public static final String CONFIG_ENABLE_PSDS_PERIODIC_DOWNLOAD = + static final String CONFIG_NFW_PROXY_APPS = "NFW_PROXY_APPS"; + private static final String CONFIG_ENABLE_PSDS_PERIODIC_DOWNLOAD = "ENABLE_PSDS_PERIODIC_DOWNLOAD"; + static final String CONFIG_LONGTERM_PSDS_SERVER_1 = "LONGTERM_PSDS_SERVER_1"; + static final String CONFIG_LONGTERM_PSDS_SERVER_2 = "LONGTERM_PSDS_SERVER_2"; + static final String CONFIG_LONGTERM_PSDS_SERVER_3 = "LONGTERM_PSDS_SERVER_3"; + static final String CONFIG_NORMAL_PSDS_SERVER = "NORMAL_PSDS_SERVER"; + static final String CONFIG_REALTIME_PSDS_SERVER = "REALTIME_PSDS_SERVER"; // Limit on NI emergency mode time extension after emergency sessions ends private static final int MAX_EMERGENCY_MODE_EXTENSION_SECONDS = 300; // 5 minute maximum @@ -202,6 +207,15 @@ public class GnssConfiguration { } /** + * Returns true if a long-term PSDS server is configured. + */ + boolean isLongTermPsdsServerConfigured() { + return (mProperties.getProperty(CONFIG_LONGTERM_PSDS_SERVER_1) != null + || mProperties.getProperty(CONFIG_LONGTERM_PSDS_SERVER_2) != null + || mProperties.getProperty(CONFIG_LONGTERM_PSDS_SERVER_3) != null); + } + + /** * Updates the GNSS HAL satellite denylist. */ void setSatelliteBlocklist(int[] constellations, int[] svids) { 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 dae2fbbc8f4c..ea99e7972887 100644 --- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java @@ -1574,6 +1574,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements pw.print(mGnssMetrics.dumpGnssMetricsAsText()); if (dumpAll) { pw.println("mSupportsPsds=" + mSupportsPsds); + pw.println( + "PsdsServerConfigured=" + mGnssConfiguration.isLongTermPsdsServerConfigured()); pw.println("native internal state: "); pw.println(" " + mGnssNative.getInternalState()); } diff --git a/services/core/java/com/android/server/location/gnss/GnssManagerService.java b/services/core/java/com/android/server/location/gnss/GnssManagerService.java index 0f9945ccdc6e..69385a92cab1 100644 --- a/services/core/java/com/android/server/location/gnss/GnssManagerService.java +++ b/services/core/java/com/android/server/location/gnss/GnssManagerService.java @@ -319,7 +319,7 @@ public class GnssManagerService { } if (mGnssAntennaInfoProvider.isSupported()) { - ipw.println("Navigation Message Provider:"); + ipw.println("Antenna Info Provider:"); ipw.increaseIndent(); ipw.println("Antenna Infos: " + mGnssAntennaInfoProvider.getAntennaInfos()); mGnssAntennaInfoProvider.dump(fd, ipw, args); diff --git a/services/core/java/com/android/server/location/gnss/GnssPsdsDownloader.java b/services/core/java/com/android/server/location/gnss/GnssPsdsDownloader.java index dce9a12ff798..243910dd9541 100644 --- a/services/core/java/com/android/server/location/gnss/GnssPsdsDownloader.java +++ b/services/core/java/com/android/server/location/gnss/GnssPsdsDownloader.java @@ -61,9 +61,12 @@ class GnssPsdsDownloader { GnssPsdsDownloader(Properties properties) { // read PSDS servers from the Properties object int count = 0; - String longTermPsdsServer1 = properties.getProperty("LONGTERM_PSDS_SERVER_1"); - String longTermPsdsServer2 = properties.getProperty("LONGTERM_PSDS_SERVER_2"); - String longTermPsdsServer3 = properties.getProperty("LONGTERM_PSDS_SERVER_3"); + String longTermPsdsServer1 = properties.getProperty( + GnssConfiguration.CONFIG_LONGTERM_PSDS_SERVER_1); + String longTermPsdsServer2 = properties.getProperty( + GnssConfiguration.CONFIG_LONGTERM_PSDS_SERVER_2); + String longTermPsdsServer3 = properties.getProperty( + GnssConfiguration.CONFIG_LONGTERM_PSDS_SERVER_3); if (longTermPsdsServer1 != null) count++; if (longTermPsdsServer2 != null) count++; if (longTermPsdsServer3 != null) count++; @@ -83,8 +86,10 @@ class GnssPsdsDownloader { mNextServerIndex = random.nextInt(count); } - String normalPsdsServer = properties.getProperty("NORMAL_PSDS_SERVER"); - String realtimePsdsServer = properties.getProperty("REALTIME_PSDS_SERVER"); + String normalPsdsServer = properties.getProperty( + GnssConfiguration.CONFIG_NORMAL_PSDS_SERVER); + String realtimePsdsServer = properties.getProperty( + GnssConfiguration.CONFIG_REALTIME_PSDS_SERVER); mPsdsServers = new String[MAX_PSDS_TYPE_INDEX + 1]; mPsdsServers[NORMAL_PSDS_SERVER_INDEX] = normalPsdsServer; mPsdsServers[REALTIME_PSDS_SERVER_INDEX] = realtimePsdsServer; diff --git a/services/core/java/com/android/server/location/gnss/hal/GnssNative.java b/services/core/java/com/android/server/location/gnss/hal/GnssNative.java index af87677ecb66..1fa56bc3e055 100644 --- a/services/core/java/com/android/server/location/gnss/hal/GnssNative.java +++ b/services/core/java/com/android/server/location/gnss/hal/GnssNative.java @@ -47,6 +47,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.List; import java.util.Objects; +import java.util.concurrent.TimeUnit; /** * Entry point for most GNSS HAL commands and callbacks. @@ -1271,7 +1272,8 @@ public class GnssNative { @NativeEntryPoint boolean isInEmergencySession() { return Binder.withCleanCallingIdentity( - () -> mEmergencyHelper.isInEmergency(mConfiguration.getEsExtensionSec())); + () -> mEmergencyHelper.isInEmergency( + TimeUnit.SECONDS.toMillis(mConfiguration.getEsExtensionSec()))); } /** diff --git a/services/core/java/com/android/server/logcat/LogAccessDialogActivity.java b/services/core/java/com/android/server/logcat/LogAccessDialogActivity.java index b45bfb1c2d92..79088d0398d2 100644 --- a/services/core/java/com/android/server/logcat/LogAccessDialogActivity.java +++ b/services/core/java/com/android/server/logcat/LogAccessDialogActivity.java @@ -116,6 +116,10 @@ public class LogAccessDialogActivity extends Activity implements } mPackageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); + if (mPackageName == null || mPackageName.length() == 0) { + throw new NullPointerException("Package Name is null"); + } + mUid = intent.getIntExtra("com.android.server.logcat.uid", 0); mGid = intent.getIntExtra("com.android.server.logcat.gid", 0); mPid = intent.getIntExtra("com.android.server.logcat.pid", 0); @@ -154,12 +158,17 @@ public class LogAccessDialogActivity extends Activity implements CharSequence appLabel = pm.getApplicationInfoAsUser(callingPackage, PackageManager.MATCH_DIRECT_BOOT_AUTO, UserHandle.getUserId(uid)).loadLabel(pm); - if (appLabel == null) { + if (appLabel == null || appLabel.length() == 0) { throw new NameNotFoundException("Application Label is null"); } - return context.getString(com.android.internal.R.string.log_access_confirmation_title, - appLabel); + String titleString = context.getString( + com.android.internal.R.string.log_access_confirmation_title, appLabel); + if (titleString == null || titleString.length() == 0) { + throw new NullPointerException("Title is null"); + } + + return titleString; } /** diff --git a/services/core/java/com/android/server/logcat/LogcatManagerService.java b/services/core/java/com/android/server/logcat/LogcatManagerService.java index f856193bca9f..5dccd071e250 100644 --- a/services/core/java/com/android/server/logcat/LogcatManagerService.java +++ b/services/core/java/com/android/server/logcat/LogcatManagerService.java @@ -208,7 +208,7 @@ public final class LogcatManagerService extends SystemService { .getUidProcessState(mUid); // If the process is foreground and we can retrieve the package name, show a dialog // for user consent - if (procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) { + if (procState == ActivityManager.PROCESS_STATE_TOP) { String packageName = getPackageName(mUid, mGid, mPid, mFd); if (packageName != null) { final Intent mIntent = createIntent(packageName, mUid, mGid, mPid, mFd); diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index 42fed365441b..9e5da450c8a5 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -1179,8 +1179,15 @@ public class MediaSessionService extends SystemService implements Monitor { @Override public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver) { - (new MediaShellCommand()).exec(this, in, out, err, args, callback, - resultReceiver); + String[] packageNames = + mContext.getPackageManager().getPackagesForUid(Binder.getCallingUid()); + String packageName = packageNames != null && packageNames.length > 0 + ? packageNames[0] + : "com.android.shell"; // We should not need this branch, but defaulting to the + // current shell package name for robustness. See + // b/227109905. + new MediaShellCommand(packageName) + .exec(this, in, out, err, args, callback, resultReceiver); } @Override diff --git a/services/core/java/com/android/server/media/MediaShellCommand.java b/services/core/java/com/android/server/media/MediaShellCommand.java index 103cdd997efc..d175d87651de 100644 --- a/services/core/java/com/android/server/media/MediaShellCommand.java +++ b/services/core/java/com/android/server/media/MediaShellCommand.java @@ -47,15 +47,19 @@ import java.util.List; * ShellCommand for MediaSessionService. */ public class MediaShellCommand extends ShellCommand { - // This doesn't belongs to any package. Setting the package name to empty string. - private static final String PACKAGE_NAME = ""; private static ActivityThread sThread; private static MediaSessionManager sMediaSessionManager; + + private final String mPackageName; private ISessionManager mSessionService; private PrintWriter mWriter; private PrintWriter mErrorWriter; private InputStream mInput; + public MediaShellCommand(String packageName) { + mPackageName = packageName; + } + @Override public int onCommand(String cmd) { mWriter = getOutPrintWriter(); @@ -110,7 +114,7 @@ public class MediaShellCommand extends ShellCommand { mWriter.println(); mWriter.println("media_session dispatch: dispatch a media key to the system."); mWriter.println(" KEY may be: play, pause, play-pause, mute, headsethook,"); - mWriter.println(" stop, next, previous, rewind, record, fast-forword."); + mWriter.println(" stop, next, previous, rewind, record, fast-forward."); mWriter.println("media_session list-sessions: print a list of the current sessions."); mWriter.println("media_session monitor: monitor updates to the specified session."); mWriter.println(" Use the tag from list-sessions."); @@ -120,7 +124,8 @@ public class MediaShellCommand extends ShellCommand { private void sendMediaKey(KeyEvent event) { try { - mSessionService.dispatchMediaKeyEvent(PACKAGE_NAME, false, event, false); + mSessionService.dispatchMediaKeyEvent( + mPackageName, /* asSystemService= */ false, event, /* needWakeLock= */ false); } catch (RemoteException e) { } } diff --git a/services/core/java/com/android/server/notification/BubbleExtractor.java b/services/core/java/com/android/server/notification/BubbleExtractor.java index 41e067e57190..a561390ac7e4 100644 --- a/services/core/java/com/android/server/notification/BubbleExtractor.java +++ b/services/core/java/com/android/server/notification/BubbleExtractor.java @@ -32,6 +32,7 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; +import android.content.res.Resources; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; @@ -49,10 +50,15 @@ public class BubbleExtractor implements NotificationSignalExtractor { private ActivityManager mActivityManager; private Context mContext; + boolean mSupportsBubble; + public void initialize(Context context, NotificationUsageStats usageStats) { if (DBG) Slog.d(TAG, "Initializing " + getClass().getSimpleName() + "."); mContext = context; mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); + + mSupportsBubble = Resources.getSystem().getBoolean( + com.android.internal.R.bool.config_supportsBubble); } public RankingReconsideration process(NotificationRecord record) { @@ -138,6 +144,10 @@ public class BubbleExtractor implements NotificationSignalExtractor { */ @VisibleForTesting boolean canPresentAsBubble(NotificationRecord r) { + if (!mSupportsBubble) { + return false; + } + Notification notification = r.getNotification(); Notification.BubbleMetadata metadata = notification.getBubbleMetadata(); String pkg = r.getSbn().getPackageName(); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index f42e734b96ec..3eee572e82f3 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -240,6 +240,7 @@ import android.service.notification.SnoozeCriterion; import android.service.notification.StatusBarNotification; import android.service.notification.ZenModeConfig; import android.service.notification.ZenModeProto; +import android.telecom.TelecomManager; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.text.TextUtils; @@ -509,6 +510,7 @@ public class NotificationManagerService extends SystemService { private ShortcutHelper mShortcutHelper; private PermissionHelper mPermissionHelper; private UsageStatsManagerInternal mUsageStatsManagerInternal; + private TelecomManager mTelecomManager; final IBinder mForegroundToken = new Binder(); private WorkerHandler mHandler; @@ -2100,7 +2102,8 @@ public class NotificationManagerService extends SystemService { NotificationHistoryManager historyManager, StatsManager statsManager, TelephonyManager telephonyManager, ActivityManagerInternal ami, MultiRateLimiter toastRateLimiter, PermissionHelper permissionHelper, - UsageStatsManagerInternal usageStatsManagerInternal) { + UsageStatsManagerInternal usageStatsManagerInternal, + TelecomManager telecomManager) { mHandler = handler; Resources resources = getContext().getResources(); mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(), @@ -2129,6 +2132,7 @@ public class NotificationManagerService extends SystemService { mDeviceIdleManager = getContext().getSystemService(DeviceIdleManager.class); mDpm = dpm; mUm = userManager; + mTelecomManager = telecomManager; mPlatformCompat = IPlatformCompat.Stub.asInterface( ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); @@ -2420,7 +2424,8 @@ public class NotificationManagerService extends SystemService { PermissionManagerServiceInternal.class), AppGlobals.getPackageManager(), AppGlobals.getPermissionManager(), mEnableAppSettingMigration, mForceUserSetOnUpgrade), - LocalServices.getService(UsageStatsManagerInternal.class)); + LocalServices.getService(UsageStatsManagerInternal.class), + getContext().getSystemService(TelecomManager.class)); publishBinderService(Context.NOTIFICATION_SERVICE, mService, /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL); @@ -5535,6 +5540,12 @@ public class NotificationManagerService extends SystemService { } @Override + public boolean isInCall(String pkg, int uid) { + checkCallerIsSystemOrSystemUiOrShell(); + return isCallNotification(pkg, uid); + } + + @Override public void setPrivateNotificationsAllowed(boolean allow) { if (PackageManager.PERMISSION_GRANTED != getContext().checkCallingPermission( @@ -5816,7 +5827,7 @@ public class NotificationManagerService extends SystemService { // Add summary final ApplicationInfo appInfo = adjustedSbn.getNotification().extras.getParcelable( - Notification.EXTRA_BUILDER_APPLICATION_INFO); + Notification.EXTRA_BUILDER_APPLICATION_INFO, ApplicationInfo.class); final Bundle extras = new Bundle(); extras.putParcelable(Notification.EXTRA_BUILDER_APPLICATION_INFO, appInfo); final String channelId = notificationRecord.getChannel().getId(); @@ -6846,7 +6857,7 @@ public class NotificationManagerService extends SystemService { synchronized (mNotificationLock) { isBlocked |= isRecordBlockedLocked(r); } - if (isBlocked && !n.isMediaNotification()) { + if (isBlocked && !(n.isMediaNotification() || isCallNotification(pkg, uid, n))) { if (DBG) { Slog.e(TAG, "Suppressing notification from package " + r.getSbn().getPackageName() + " by user request."); @@ -6858,6 +6869,23 @@ public class NotificationManagerService extends SystemService { return true; } + private boolean isCallNotification(String pkg, int uid, Notification n) { + if (n.isStyle(Notification.CallStyle.class)) { + return isCallNotification(pkg, uid); + } + return false; + } + + private boolean isCallNotification(String pkg, int uid) { + final long identity = Binder.clearCallingIdentity(); + try { + return mTelecomManager.isInManagedCall() || mTelecomManager.isInSelfManagedCall( + pkg, UserHandle.getUserHandleForUid(uid)); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + private boolean areNotificationsEnabledForPackageInt(String pkg, int uid) { if (mEnableAppSettingMigration) { return mPermissionHelper.hasPermission(uid); diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java index bbdea32bed59..f979343248f1 100644 --- a/services/core/java/com/android/server/notification/NotificationRecord.java +++ b/services/core/java/com/android/server/notification/NotificationRecord.java @@ -1348,14 +1348,14 @@ public final class NotificationRecord { protected void calculateGrantableUris() { final Notification notification = getNotification(); notification.visitUris((uri) -> { - visitGrantableUri(uri, false); + visitGrantableUri(uri, false, false); }); if (notification.getChannelId() != null) { NotificationChannel channel = getChannel(); if (channel != null) { visitGrantableUri(channel.getSound(), (channel.getUserLockedFields() - & NotificationChannel.USER_LOCKED_SOUND) != 0); + & NotificationChannel.USER_LOCKED_SOUND) != 0, true); } } } @@ -1368,7 +1368,7 @@ public final class NotificationRecord { * {@link #mGrantableUris}. Otherwise, this will either log or throw * {@link SecurityException} depending on target SDK of enqueuing app. */ - private void visitGrantableUri(Uri uri, boolean userOverriddenUri) { + private void visitGrantableUri(Uri uri, boolean userOverriddenUri, boolean isSound) { if (uri == null || !ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) return; // We can't grant Uri permissions from system @@ -1389,10 +1389,16 @@ public final class NotificationRecord { mGrantableUris.add(uri); } catch (SecurityException e) { if (!userOverriddenUri) { - if (mTargetSdkVersion >= Build.VERSION_CODES.P) { - throw e; + if (isSound) { + mSound = Settings.System.DEFAULT_NOTIFICATION_URI; + Log.w(TAG, "Replacing " + uri + " from " + sourceUid + ": " + e.getMessage()); } else { - Log.w(TAG, "Ignoring " + uri + " from " + sourceUid + ": " + e.getMessage()); + if (mTargetSdkVersion >= Build.VERSION_CODES.P) { + throw e; + } else { + Log.w(TAG, + "Ignoring " + uri + " from " + sourceUid + ": " + e.getMessage()); + } } } } finally { diff --git a/services/core/java/com/android/server/notification/PermissionHelper.java b/services/core/java/com/android/server/notification/PermissionHelper.java index b4230c11bcab..a09aa7cea0a4 100644 --- a/services/core/java/com/android/server/notification/PermissionHelper.java +++ b/services/core/java/com/android/server/notification/PermissionHelper.java @@ -55,8 +55,10 @@ public final class PermissionHelper { private final PermissionManagerServiceInternal mPmi; private final IPackageManager mPackageManager; private final IPermissionManager mPermManager; - // TODO (b/194833441): Remove when the migration is enabled + // TODO (b/194833441): Remove this boolean (but keep the isMigrationEnabled() method) + // when the migration is enabled private final boolean mMigrationEnabled; + private final boolean mIsTv; private final boolean mForceUserSetOnUpgrade; public PermissionHelper(PermissionManagerServiceInternal pmi, IPackageManager packageManager, @@ -67,10 +69,17 @@ public final class PermissionHelper { mPermManager = permManager; mMigrationEnabled = migrationEnabled; mForceUserSetOnUpgrade = forceUserSetOnUpgrade; + boolean isTv; + try { + isTv = mPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK, 0); + } catch (RemoteException e) { + isTv = false; + } + mIsTv = isTv; } public boolean isMigrationEnabled() { - return mMigrationEnabled; + return mMigrationEnabled && !mIsTv; } /** diff --git a/services/core/java/com/android/server/pm/AppsFilterImpl.java b/services/core/java/com/android/server/pm/AppsFilterImpl.java index 5865adb96333..dff7100e90e3 100644 --- a/services/core/java/com/android/server/pm/AppsFilterImpl.java +++ b/services/core/java/com/android/server/pm/AppsFilterImpl.java @@ -76,6 +76,7 @@ import com.android.server.utils.Watcher; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.Set; @@ -102,6 +103,7 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable * application B is implicitly allowed to query for application A; regardless of any manifest * entries. */ + @GuardedBy("mLock") @Watched private final WatchedSparseSetArray<Integer> mImplicitlyQueryable; private final SnapshotCache<WatchedSparseSetArray<Integer>> mImplicitQueryableSnapshot; @@ -111,6 +113,7 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable * interacted with it, but could keep across package updates. For example, if application A * grants persistable uri permission to application B; regardless of any manifest entries. */ + @GuardedBy("mLock") @Watched private final WatchedSparseSetArray<Integer> mRetainedImplicitlyQueryable; private final SnapshotCache<WatchedSparseSetArray<Integer>> @@ -120,6 +123,7 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable * A mapping from the set of App IDs that query other App IDs via package name to the * list of packages that they can see. */ + @GuardedBy("mLock") @Watched private final WatchedSparseSetArray<Integer> mQueriesViaPackage; private final SnapshotCache<WatchedSparseSetArray<Integer>> mQueriesViaPackageSnapshot; @@ -128,6 +132,7 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable * A mapping from the set of App IDs that query others via component match to the list * of packages that the they resolve to. */ + @GuardedBy("mLock") @Watched private final WatchedSparseSetArray<Integer> mQueriesViaComponent; private final SnapshotCache<WatchedSparseSetArray<Integer>> mQueriesViaComponentSnapshot; @@ -136,6 +141,7 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable * A mapping from the set of App IDs that query other App IDs via library name to the * list of packages that they can see. */ + @GuardedBy("mLock") @Watched private final WatchedSparseSetArray<Integer> mQueryableViaUsesLibrary; private final SnapshotCache<WatchedSparseSetArray<Integer>> mQueryableViaUsesLibrarySnapshot; @@ -158,6 +164,7 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable * A set of App IDs that are always queryable by any package, regardless of their manifest * content. */ + @GuardedBy("mLock") @Watched private final WatchedArraySet<Integer> mForceQueryable; private final SnapshotCache<WatchedArraySet<Integer>> mForceQueryableSnapshot; @@ -173,9 +180,9 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable private final FeatureConfig mFeatureConfig; private final OverlayReferenceMapper mOverlayReferenceMapper; private final StateProvider mStateProvider; - private final PackageManagerInternal mPmInternal; private SigningDetails mSystemSigningDetails; + @GuardedBy("mLock") @Watched private final WatchedArrayList<String> mProtectedBroadcasts; private final SnapshotCache<WatchedArrayList<String>> mProtectedBroadcastsSnapshot; @@ -197,6 +204,11 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable private volatile boolean mSystemReady = false; /** + * Guards the accesses for the list/set fields except for {@link #mShouldFilterCache} + */ + private final Object mLock = new Object(); + + /** * A cached snapshot. */ private final SnapshotCache<AppsFilterImpl> mSnapshot; @@ -216,15 +228,6 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable * Watchable machinery */ private final WatchableImpl mWatchable = new WatchableImpl(); - /** - * The observer that watches for changes from array members - */ - private final Watcher mObserver = new Watcher() { - @Override - public void onChange(@Nullable Watchable what) { - AppsFilterImpl.this.dispatchChange(what); - } - }; /** * Ensures an observer is in the list, exactly once. The observer cannot be null. The @@ -284,15 +287,13 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable String[] forceQueryableList, boolean systemAppsQueryable, @Nullable OverlayReferenceMapper.Provider overlayProvider, - Executor backgroundExecutor, - PackageManagerInternal pmInternal) { + Executor backgroundExecutor) { mFeatureConfig = featureConfig; mForceQueryableByDevicePackageNames = forceQueryableList; mSystemAppsQueryable = systemAppsQueryable; mOverlayReferenceMapper = new OverlayReferenceMapper(true /*deferRebuild*/, overlayProvider); mStateProvider = stateProvider; - mPmInternal = pmInternal; mBackgroundExecutor = backgroundExecutor; mShouldFilterCache = new WatchedSparseBooleanMatrix(); mShouldFilterCacheSnapshot = new SnapshotCache.Auto<>( @@ -321,8 +322,6 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable mProtectedBroadcastsSnapshot = new SnapshotCache.Auto<>( mProtectedBroadcasts, mProtectedBroadcasts, "AppsFilter.mProtectedBroadcasts"); - registerObservers(); - Watchable.verifyWatchedAttributes(this, mObserver); mSnapshot = makeCache(); } @@ -330,20 +329,22 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable * The copy constructor is used by PackageManagerService to construct a snapshot. */ private AppsFilterImpl(AppsFilterImpl orig) { - mImplicitlyQueryable = orig.mImplicitQueryableSnapshot.snapshot(); - mImplicitQueryableSnapshot = new SnapshotCache.Sealed<>(); - mRetainedImplicitlyQueryable = orig.mRetainedImplicitlyQueryableSnapshot.snapshot(); - mRetainedImplicitlyQueryableSnapshot = new SnapshotCache.Sealed<>(); - mQueriesViaPackage = orig.mQueriesViaPackageSnapshot.snapshot(); - mQueriesViaPackageSnapshot = new SnapshotCache.Sealed<>(); - mQueriesViaComponent = orig.mQueriesViaComponentSnapshot.snapshot(); - mQueriesViaComponentSnapshot = new SnapshotCache.Sealed<>(); - mQueryableViaUsesLibrary = orig.mQueryableViaUsesLibrarySnapshot.snapshot(); - mQueryableViaUsesLibrarySnapshot = new SnapshotCache.Sealed<>(); - mForceQueryable = orig.mForceQueryableSnapshot.snapshot(); - mForceQueryableSnapshot = new SnapshotCache.Sealed<>(); - mProtectedBroadcasts = orig.mProtectedBroadcastsSnapshot.snapshot(); - mProtectedBroadcastsSnapshot = new SnapshotCache.Sealed<>(); + synchronized (orig.mLock) { + mImplicitlyQueryable = orig.mImplicitQueryableSnapshot.snapshot(); + mImplicitQueryableSnapshot = new SnapshotCache.Sealed<>(); + mRetainedImplicitlyQueryable = orig.mRetainedImplicitlyQueryableSnapshot.snapshot(); + mRetainedImplicitlyQueryableSnapshot = new SnapshotCache.Sealed<>(); + mQueriesViaPackage = orig.mQueriesViaPackageSnapshot.snapshot(); + mQueriesViaPackageSnapshot = new SnapshotCache.Sealed<>(); + mQueriesViaComponent = orig.mQueriesViaComponentSnapshot.snapshot(); + mQueriesViaComponentSnapshot = new SnapshotCache.Sealed<>(); + mQueryableViaUsesLibrary = orig.mQueryableViaUsesLibrarySnapshot.snapshot(); + mQueryableViaUsesLibrarySnapshot = new SnapshotCache.Sealed<>(); + mForceQueryable = orig.mForceQueryableSnapshot.snapshot(); + mForceQueryableSnapshot = new SnapshotCache.Sealed<>(); + mProtectedBroadcasts = orig.mProtectedBroadcastsSnapshot.snapshot(); + mProtectedBroadcastsSnapshot = new SnapshotCache.Sealed<>(); + } mQueriesViaComponentRequireRecompute = orig.mQueriesViaComponentRequireRecompute; mForceQueryableByDevicePackageNames = Arrays.copyOf(orig.mForceQueryableByDevicePackageNames, @@ -359,23 +360,10 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable } mBackgroundExecutor = null; - mPmInternal = null; mSnapshot = new SnapshotCache.Sealed<>(); mSystemReady = true; } - @SuppressWarnings("GuardedBy") - private void registerObservers() { - mImplicitlyQueryable.registerObserver(mObserver); - mRetainedImplicitlyQueryable.registerObserver(mObserver); - mQueriesViaPackage.registerObserver(mObserver); - mQueriesViaComponent.registerObserver(mObserver); - mQueryableViaUsesLibrary.registerObserver(mObserver); - mForceQueryable.registerObserver(mObserver); - mProtectedBroadcasts.registerObserver(mObserver); - mShouldFilterCache.registerObserver(mObserver); - } - /** * Return a snapshot. If the cached snapshot is null, build a new one. The logic in * the function ensures that this function returns a valid snapshot even if a race @@ -397,6 +385,7 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable interface CurrentStateCallback { void currentState(ArrayMap<String, ? extends PackageStateInternal> settings, + Collection<SharedUserSetting> sharedUserSettings, UserInfo[] users); } } @@ -588,12 +577,13 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable final StateProvider stateProvider = command -> { synchronized (injector.getLock()) { command.currentState(injector.getSettings().getPackagesLocked().untrackedStorage(), + injector.getSettings().getAllSharedUsersLPw(), injector.getUserManagerInternal().getUserInfos()); } }; AppsFilterImpl appsFilter = new AppsFilterImpl(stateProvider, featureConfig, forcedQueryablePackageNames, forceSystemAppsQueryable, null, - injector.getBackgroundExecutor(), pmInt); + injector.getBackgroundExecutor()); featureConfig.setAppsFilter(appsFilter); return appsFilter; } @@ -743,9 +733,11 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable return false; } final boolean changed; - changed = retainOnUpdate - ? mRetainedImplicitlyQueryable.add(recipientUid, visibleUid) - : mImplicitlyQueryable.add(recipientUid, visibleUid); + synchronized (mLock) { + changed = retainOnUpdate + ? mRetainedImplicitlyQueryable.add(recipientUid, visibleUid) + : mImplicitlyQueryable.add(recipientUid, visibleUid); + } if (changed && DEBUG_LOGGING) { Slog.i(TAG, (retainOnUpdate ? "retained " : "") + "implicit access granted: " + recipientUid + " -> " + visibleUid); @@ -758,9 +750,7 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable mShouldFilterCache.put(recipientUid, visibleUid, false); } } - if (changed) { - onChanged(); - } + onChanged(); return changed; } @@ -788,7 +778,7 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable // let's first remove any prior rules for this package removePackage(newPkgSetting, true /*isReplace*/); } - mStateProvider.runWithState((settings, users) -> { + mStateProvider.runWithState((settings, sharedUserSettings, users) -> { ArraySet<String> additionalChangedPackages = addPackageInternal(newPkgSetting, settings); if (mSystemReady) { @@ -806,9 +796,8 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable continue; } - updateShouldFilterCacheForPackage(null, - changedPkgSetting, settings, users, USER_ALL, - settings.size()); + updateShouldFilterCacheForPackage(null, changedPkgSetting, + settings, users, USER_ALL, settings.size()); } } } // else, rebuild entire cache when system is ready @@ -835,7 +824,9 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable // packages for signature matches for (PackageStateInternal setting : existingSettings.values()) { if (isSystemSigned(mSystemSigningDetails, setting)) { - mForceQueryable.add(setting.getAppId()); + synchronized (mLock) { + mForceQueryable.add(setting.getAppId()); + } } } } @@ -845,75 +836,76 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable return null; } - if (mProtectedBroadcasts.addAll(newPkg.getProtectedBroadcasts())) { - mQueriesViaComponentRequireRecompute = true; - } - - final boolean newIsForceQueryable = - mForceQueryable.contains(newPkgSetting.getAppId()) - /* shared user that is already force queryable */ - || newPkgSetting.isForceQueryableOverride() /* adb override */ - || (newPkgSetting.isSystem() && (mSystemAppsQueryable - || newPkg.isForceQueryable() - || ArrayUtils.contains(mForceQueryableByDevicePackageNames, - newPkg.getPackageName()))); - if (newIsForceQueryable - || (mSystemSigningDetails != null - && isSystemSigned(mSystemSigningDetails, newPkgSetting))) { - mForceQueryable.add(newPkgSetting.getAppId()); - } + synchronized (mLock) { + if (mProtectedBroadcasts.addAll(newPkg.getProtectedBroadcasts())) { + mQueriesViaComponentRequireRecompute = true; + } - for (int i = existingSettings.size() - 1; i >= 0; i--) { - final PackageStateInternal existingSetting = existingSettings.valueAt(i); - if (existingSetting.getAppId() == newPkgSetting.getAppId() - || existingSetting.getPkg() - == null) { - continue; + final boolean newIsForceQueryable = + mForceQueryable.contains(newPkgSetting.getAppId()) + /* shared user that is already force queryable */ + || newPkgSetting.isForceQueryableOverride() /* adb override */ + || (newPkgSetting.isSystem() && (mSystemAppsQueryable + || newPkg.isForceQueryable() + || ArrayUtils.contains(mForceQueryableByDevicePackageNames, + newPkg.getPackageName()))); + if (newIsForceQueryable + || (mSystemSigningDetails != null + && isSystemSigned(mSystemSigningDetails, newPkgSetting))) { + mForceQueryable.add(newPkgSetting.getAppId()); } - final AndroidPackage existingPkg = existingSetting.getPkg(); - // let's evaluate the ability of already added packages to see this new package - if (!newIsForceQueryable) { - if (!mQueriesViaComponentRequireRecompute && canQueryViaComponents(existingPkg, - newPkg, mProtectedBroadcasts)) { - mQueriesViaComponent.add(existingSetting.getAppId(), - newPkgSetting.getAppId()); - } - if (canQueryViaPackage(existingPkg, newPkg) - || canQueryAsInstaller(existingSetting, newPkg)) { - mQueriesViaPackage.add(existingSetting.getAppId(), - newPkgSetting.getAppId()); - } - if (canQueryViaUsesLibrary(existingPkg, newPkg)) { - mQueryableViaUsesLibrary.add(existingSetting.getAppId(), - newPkgSetting.getAppId()); + + for (int i = existingSettings.size() - 1; i >= 0; i--) { + final PackageStateInternal existingSetting = existingSettings.valueAt(i); + if (existingSetting.getAppId() == newPkgSetting.getAppId() + || existingSetting.getPkg() + == null) { + continue; } - } - // now we'll evaluate our new package's ability to see existing packages - if (!mForceQueryable.contains(existingSetting.getAppId())) { - if (!mQueriesViaComponentRequireRecompute && canQueryViaComponents(newPkg, - existingPkg, mProtectedBroadcasts)) { - mQueriesViaComponent.add(newPkgSetting.getAppId(), - existingSetting.getAppId()); + final AndroidPackage existingPkg = existingSetting.getPkg(); + // let's evaluate the ability of already added packages to see this new package + if (!newIsForceQueryable) { + if (!mQueriesViaComponentRequireRecompute && canQueryViaComponents(existingPkg, + newPkg, mProtectedBroadcasts)) { + mQueriesViaComponent.add(existingSetting.getAppId(), + newPkgSetting.getAppId()); + } + if (canQueryViaPackage(existingPkg, newPkg) + || canQueryAsInstaller(existingSetting, newPkg)) { + mQueriesViaPackage.add(existingSetting.getAppId(), + newPkgSetting.getAppId()); + } + if (canQueryViaUsesLibrary(existingPkg, newPkg)) { + mQueryableViaUsesLibrary.add(existingSetting.getAppId(), + newPkgSetting.getAppId()); + } } - if (canQueryViaPackage(newPkg, existingPkg) - || canQueryAsInstaller(newPkgSetting, existingPkg)) { - mQueriesViaPackage.add(newPkgSetting.getAppId(), - existingSetting.getAppId()); + // now we'll evaluate our new package's ability to see existing packages + if (!mForceQueryable.contains(existingSetting.getAppId())) { + if (!mQueriesViaComponentRequireRecompute && canQueryViaComponents(newPkg, + existingPkg, mProtectedBroadcasts)) { + mQueriesViaComponent.add(newPkgSetting.getAppId(), + existingSetting.getAppId()); + } + if (canQueryViaPackage(newPkg, existingPkg) + || canQueryAsInstaller(newPkgSetting, existingPkg)) { + mQueriesViaPackage.add(newPkgSetting.getAppId(), + existingSetting.getAppId()); + } + if (canQueryViaUsesLibrary(newPkg, existingPkg)) { + mQueryableViaUsesLibrary.add(newPkgSetting.getAppId(), + existingSetting.getAppId()); + } } - if (canQueryViaUsesLibrary(newPkg, existingPkg)) { - mQueryableViaUsesLibrary.add(newPkgSetting.getAppId(), - existingSetting.getAppId()); + // if either package instruments the other, mark both as visible to one another + if (newPkgSetting.getPkg() != null && existingSetting.getPkg() != null + && (pkgInstruments(newPkgSetting.getPkg(), existingSetting.getPkg()) + || pkgInstruments(existingSetting.getPkg(), newPkgSetting.getPkg()))) { + mQueriesViaPackage.add(newPkgSetting.getAppId(), existingSetting.getAppId()); + mQueriesViaPackage.add(existingSetting.getAppId(), newPkgSetting.getAppId()); } } - // if either package instruments the other, mark both as visible to one another - if (newPkgSetting.getPkg() != null && existingSetting.getPkg() != null - && (pkgInstruments(newPkgSetting.getPkg(), existingSetting.getPkg()) - || pkgInstruments(existingSetting.getPkg(), newPkgSetting.getPkg()))) { - mQueriesViaPackage.add(newPkgSetting.getAppId(), existingSetting.getAppId()); - mQueriesViaPackage.add(existingSetting.getAppId(), newPkgSetting.getAppId()); - } } - int existingSize = existingSettings.size(); ArrayMap<String, AndroidPackage> existingPkgs = new ArrayMap<>(existingSize); for (int index = 0; index < existingSize; index++) { @@ -954,7 +946,7 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable } private void updateEntireShouldFilterCache(int subjectUserId) { - mStateProvider.runWithState((settings, users) -> { + mStateProvider.runWithState((settings, sharedUserSettings, users) -> { int userId = USER_NULL; for (int u = 0; u < users.length; u++) { if (subjectUserId == users[u].id) { @@ -969,10 +961,12 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable } updateEntireShouldFilterCacheInner(settings, users, userId); }); + onChanged(); } private void updateEntireShouldFilterCacheInner( - ArrayMap<String, ? extends PackageStateInternal> settings, UserInfo[] users, + ArrayMap<String, ? extends PackageStateInternal> settings, + UserInfo[] users, int subjectUserId) { synchronized (mCacheLock) { if (subjectUserId == USER_ALL) { @@ -982,16 +976,18 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable } for (int i = settings.size() - 1; i >= 0; i--) { updateShouldFilterCacheForPackage( - null /*skipPackage*/, settings.valueAt(i), settings, users, subjectUserId, i); + null /*skipPackage*/, settings.valueAt(i), settings, users, + subjectUserId, i); } } private void updateEntireShouldFilterCacheAsync() { mBackgroundExecutor.execute(() -> { final ArrayMap<String, PackageStateInternal> settingsCopy = new ArrayMap<>(); + final Collection<SharedUserSetting> sharedUserSettingsCopy = new ArraySet<>(); final ArrayMap<String, AndroidPackage> packagesCache = new ArrayMap<>(); final UserInfo[][] usersRef = new UserInfo[1][]; - mStateProvider.runWithState((settings, users) -> { + mStateProvider.runWithState((settings, sharedUserSettings, users) -> { packagesCache.ensureCapacity(settings.size()); settingsCopy.putAll(settings); usersRef[0] = users; @@ -1001,11 +997,12 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable final AndroidPackage pkg = settings.valueAt(i).getPkg(); packagesCache.put(settings.keyAt(i), pkg); } + sharedUserSettingsCopy.addAll(sharedUserSettings); }); boolean[] changed = new boolean[1]; // We have a cache, let's make sure the world hasn't changed out from under us. - mStateProvider.runWithState((settings, users) -> { + mStateProvider.runWithState((settings, sharedUserSettings, users) -> { if (settings.size() != settingsCopy.size()) { changed[0] = true; return; @@ -1025,7 +1022,9 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable Slog.i(TAG, "Rebuilding cache with lock due to package change."); } } else { - updateEntireShouldFilterCacheInner(settingsCopy, usersRef[0], USER_ALL); + updateEntireShouldFilterCacheInner(settingsCopy, + usersRef[0], USER_ALL); + onChanged(); } }); } @@ -1035,7 +1034,6 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable return; } updateEntireShouldFilterCache(newUserId); - onChanged(); } public void onUserDeleted(@UserIdInt int userId) { @@ -1047,7 +1045,7 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable } private void updateShouldFilterCacheForPackage(String packageName) { - mStateProvider.runWithState((settings, users) -> { + mStateProvider.runWithState((settings, sharedUserSettings, users) -> { if (!mSystemReady) { return; } @@ -1055,6 +1053,7 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable settings.get(packageName), settings, users, USER_ALL, settings.size() /*maxIndex*/); }); + onChanged(); } private void updateShouldFilterCacheForPackage( @@ -1134,16 +1133,18 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable private void collectProtectedBroadcasts( ArrayMap<String, ? extends PackageStateInternal> existingSettings, @Nullable String excludePackage) { - mProtectedBroadcasts.clear(); - for (int i = existingSettings.size() - 1; i >= 0; i--) { - PackageStateInternal setting = existingSettings.valueAt(i); - if (setting.getPkg() == null || setting.getPkg().getPackageName().equals( - excludePackage)) { - continue; - } - final List<String> protectedBroadcasts = setting.getPkg().getProtectedBroadcasts(); - if (!protectedBroadcasts.isEmpty()) { - mProtectedBroadcasts.addAll(protectedBroadcasts); + synchronized (mLock) { + mProtectedBroadcasts.clear(); + for (int i = existingSettings.size() - 1; i >= 0; i--) { + PackageStateInternal setting = existingSettings.valueAt(i); + if (setting.getPkg() == null || setting.getPkg().getPackageName().equals( + excludePackage)) { + continue; + } + final List<String> protectedBroadcasts = setting.getPkg().getProtectedBroadcasts(); + if (!protectedBroadcasts.isEmpty()) { + mProtectedBroadcasts.addAll(protectedBroadcasts); + } } } } @@ -1154,24 +1155,26 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable */ private void recomputeComponentVisibility( ArrayMap<String, ? extends PackageStateInternal> existingSettings) { - mQueriesViaComponent.clear(); - for (int i = existingSettings.size() - 1; i >= 0; i--) { - PackageStateInternal setting = existingSettings.valueAt(i); - if (setting.getPkg() == null || requestsQueryAllPackages(setting.getPkg())) { - continue; - } - for (int j = existingSettings.size() - 1; j >= 0; j--) { - if (i == j) { - continue; - } - final PackageStateInternal otherSetting = existingSettings.valueAt(j); - if (otherSetting.getPkg() == null || mForceQueryable.contains( - otherSetting.getAppId())) { + synchronized (mLock) { + mQueriesViaComponent.clear(); + for (int i = existingSettings.size() - 1; i >= 0; i--) { + PackageStateInternal setting = existingSettings.valueAt(i); + if (setting.getPkg() == null || requestsQueryAllPackages(setting.getPkg())) { continue; } - if (canQueryViaComponents(setting.getPkg(), otherSetting.getPkg(), - mProtectedBroadcasts)) { - mQueriesViaComponent.add(setting.getAppId(), otherSetting.getAppId()); + for (int j = existingSettings.size() - 1; j >= 0; j--) { + if (i == j) { + continue; + } + final PackageStateInternal otherSetting = existingSettings.valueAt(j); + if (otherSetting.getPkg() == null || mForceQueryable.contains( + otherSetting.getAppId())) { + continue; + } + if (canQueryViaComponents(setting.getPkg(), otherSetting.getPkg(), + mProtectedBroadcasts)) { + mQueriesViaComponent.add(setting.getAppId(), otherSetting.getAppId()); + } } } } @@ -1185,8 +1188,10 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable @Nullable public SparseArray<int[]> getVisibilityAllowList(PackageStateInternal setting, int[] users, ArrayMap<String, ? extends PackageStateInternal> existingSettings) { - if (mForceQueryable.contains(setting.getAppId())) { - return null; + synchronized (mLock) { + if (mForceQueryable.contains(setting.getAppId())) { + return null; + } } // let's reserve max memory to limit the number of allocations SparseArray<int[]> result = new SparseArray<>(users.length); @@ -1249,57 +1254,59 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable * @param isReplace if the package is being replaced. */ public void removePackage(PackageStateInternal setting, boolean isReplace) { - mStateProvider.runWithState((settings, users) -> { + mStateProvider.runWithState((settings, sharedUserSettings, users) -> { final ArraySet<String> additionalChangedPackages; final int userCount = users.length; - for (int u = 0; u < userCount; u++) { - final int userId = users[u].id; - final int removingUid = UserHandle.getUid(userId, setting.getAppId()); - mImplicitlyQueryable.remove(removingUid); - for (int i = mImplicitlyQueryable.size() - 1; i >= 0; i--) { - mImplicitlyQueryable.remove(mImplicitlyQueryable.keyAt(i), - removingUid); - } + synchronized (mLock) { + for (int u = 0; u < userCount; u++) { + final int userId = users[u].id; + final int removingUid = UserHandle.getUid(userId, setting.getAppId()); + mImplicitlyQueryable.remove(removingUid); + for (int i = mImplicitlyQueryable.size() - 1; i >= 0; i--) { + mImplicitlyQueryable.remove(mImplicitlyQueryable.keyAt(i), + removingUid); + } - if (isReplace) { - continue; - } + if (isReplace) { + continue; + } - mRetainedImplicitlyQueryable.remove(removingUid); - for (int i = mRetainedImplicitlyQueryable.size() - 1; i >= 0; i--) { - mRetainedImplicitlyQueryable.remove( - mRetainedImplicitlyQueryable.keyAt(i), removingUid); + mRetainedImplicitlyQueryable.remove(removingUid); + for (int i = mRetainedImplicitlyQueryable.size() - 1; i >= 0; i--) { + mRetainedImplicitlyQueryable.remove( + mRetainedImplicitlyQueryable.keyAt(i), removingUid); + } } - } - if (!mQueriesViaComponentRequireRecompute) { - mQueriesViaComponent.remove(setting.getAppId()); - for (int i = mQueriesViaComponent.size() - 1; i >= 0; i--) { - mQueriesViaComponent.remove(mQueriesViaComponent.keyAt(i), + if (!mQueriesViaComponentRequireRecompute) { + mQueriesViaComponent.remove(setting.getAppId()); + for (int i = mQueriesViaComponent.size() - 1; i >= 0; i--) { + mQueriesViaComponent.remove(mQueriesViaComponent.keyAt(i), + setting.getAppId()); + } + } + mQueriesViaPackage.remove(setting.getAppId()); + for (int i = mQueriesViaPackage.size() - 1; i >= 0; i--) { + mQueriesViaPackage.remove(mQueriesViaPackage.keyAt(i), + setting.getAppId()); + } + mQueryableViaUsesLibrary.remove(setting.getAppId()); + for (int i = mQueryableViaUsesLibrary.size() - 1; i >= 0; i--) { + mQueryableViaUsesLibrary.remove(mQueryableViaUsesLibrary.keyAt(i), setting.getAppId()); } - } - mQueriesViaPackage.remove(setting.getAppId()); - for (int i = mQueriesViaPackage.size() - 1; i >= 0; i--) { - mQueriesViaPackage.remove(mQueriesViaPackage.keyAt(i), - setting.getAppId()); - } - mQueryableViaUsesLibrary.remove(setting.getAppId()); - for (int i = mQueryableViaUsesLibrary.size() - 1; i >= 0; i--) { - mQueryableViaUsesLibrary.remove(mQueryableViaUsesLibrary.keyAt(i), - setting.getAppId()); - } - mForceQueryable.remove(setting.getAppId()); + mForceQueryable.remove(setting.getAppId()); - if (setting.getPkg() != null - && !setting.getPkg().getProtectedBroadcasts().isEmpty()) { - final String removingPackageName = setting.getPkg().getPackageName(); - final ArrayList<String> protectedBroadcasts = new ArrayList<>(); - protectedBroadcasts.addAll(mProtectedBroadcasts.untrackedStorage()); - collectProtectedBroadcasts(settings, removingPackageName); - if (!mProtectedBroadcasts.containsAll(protectedBroadcasts)) { - mQueriesViaComponentRequireRecompute = true; + if (setting.getPkg() != null + && !setting.getPkg().getProtectedBroadcasts().isEmpty()) { + final String removingPackageName = setting.getPkg().getPackageName(); + final ArrayList<String> protectedBroadcasts = new ArrayList<>(); + protectedBroadcasts.addAll(mProtectedBroadcasts.untrackedStorage()); + collectProtectedBroadcasts(settings, removingPackageName); + if (!mProtectedBroadcasts.containsAll(protectedBroadcasts)) { + mQueriesViaComponentRequireRecompute = true; + } } } @@ -1314,8 +1321,8 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable // update the // cache if (setting.hasSharedUser()) { - final ArraySet<PackageStateInternal> sharedUserPackages = - mPmInternal.getSharedUserPackages(setting.getSharedUserAppId()); + final ArraySet<? extends PackageStateInternal> sharedUserPackages = + getSharedUserPackages(setting.getSharedUserAppId(), sharedUserSettings); for (int i = sharedUserPackages.size() - 1; i >= 0; i--) { if (sharedUserPackages.valueAt(i) == setting) { continue; @@ -1327,8 +1334,8 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable removeAppIdFromVisibilityCache(setting.getAppId()); if (mSystemReady && setting.hasSharedUser()) { - final ArraySet<PackageStateInternal> sharedUserPackages = - mPmInternal.getSharedUserPackages(setting.getSharedUserAppId()); + final ArraySet<? extends PackageStateInternal> sharedUserPackages = + getSharedUserPackages(setting.getSharedUserAppId(), sharedUserSettings); for (int i = sharedUserPackages.size() - 1; i >= 0; i--) { PackageStateInternal siblingSetting = sharedUserPackages.valueAt(i); @@ -1336,8 +1343,8 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable continue; } updateShouldFilterCacheForPackage( - setting.getPackageName(), siblingSetting, settings, users, - USER_ALL, settings.size()); + setting.getPackageName(), siblingSetting, settings, + users, USER_ALL, settings.size()); } } @@ -1353,14 +1360,24 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable continue; } - updateShouldFilterCacheForPackage(null, - changedPkgSetting, settings, users, USER_ALL, settings.size()); + updateShouldFilterCacheForPackage(null, changedPkgSetting, + settings, users, USER_ALL, settings.size()); } } } - - onChanged(); }); + onChanged(); + } + + private ArraySet<? extends PackageStateInternal> getSharedUserPackages(int sharedUserAppId, + Collection<SharedUserSetting> sharedUserSettings) { + for (SharedUserSetting setting : sharedUserSettings) { + if (setting.mAppId != sharedUserAppId) { + continue; + } + return setting.getPackageStates(); + } + return new ArraySet<>(); } /** @@ -1441,23 +1458,26 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable return true; } final PackageStateInternal callingPkgSetting; - final ArraySet<? extends PackageStateInternal> callingSharedPkgSettings; if (DEBUG_TRACING) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "callingSetting instanceof"); } + final ArraySet<PackageStateInternal> callingSharedPkgSettings = new ArraySet<>(); + if (callingSetting instanceof PackageStateInternal) { final PackageStateInternal packageState = (PackageStateInternal) callingSetting; if (packageState.hasSharedUser()) { callingPkgSetting = null; - callingSharedPkgSettings = mPmInternal.getSharedUserPackages( - packageState.getSharedUserAppId()); + mStateProvider.runWithState((settings, sharedUserSettings, users) -> + callingSharedPkgSettings.addAll(getSharedUserPackages( + packageState.getSharedUserAppId(), sharedUserSettings))); + } else { callingPkgSetting = packageState; - callingSharedPkgSettings = null; } } else { callingPkgSetting = null; - callingSharedPkgSettings = ((SharedUserSetting) callingSetting).getPackageStates(); + callingSharedPkgSettings.addAll( + ((SharedUserSetting) callingSetting).getPackageStates()); } if (DEBUG_TRACING) { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); @@ -1545,11 +1565,13 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable if (DEBUG_TRACING) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mForceQueryable"); } - if (mForceQueryable.contains(targetAppId)) { - if (DEBUG_LOGGING) { - log(callingSetting, targetPkgSetting, "force queryable"); + synchronized (mLock) { + if (mForceQueryable.contains(targetAppId)) { + if (DEBUG_LOGGING) { + log(callingSetting, targetPkgSetting, "force queryable"); + } + return false; } - return false; } } finally { if (DEBUG_TRACING) { @@ -1560,11 +1582,13 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable if (DEBUG_TRACING) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mQueriesViaPackage"); } - if (mQueriesViaPackage.contains(callingAppId, targetAppId)) { - if (DEBUG_LOGGING) { - log(callingSetting, targetPkgSetting, "queries package"); + synchronized (mLock) { + if (mQueriesViaPackage.contains(callingAppId, targetAppId)) { + if (DEBUG_LOGGING) { + log(callingSetting, targetPkgSetting, "queries package"); + } + return false; } - return false; } } finally { if (DEBUG_TRACING) { @@ -1576,15 +1600,20 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mQueriesViaComponent"); } if (mQueriesViaComponentRequireRecompute) { - mStateProvider.runWithState((settings, users) -> { - recomputeComponentVisibility(settings); + final ArrayMap<String, PackageStateInternal> settingsCopy = new ArrayMap<>(); + mStateProvider.runWithState((settings, sharedUserSettings, users) -> { + settingsCopy.putAll(settings); }); + recomputeComponentVisibility(settingsCopy); + onChanged(); } - if (mQueriesViaComponent.contains(callingAppId, targetAppId)) { - if (DEBUG_LOGGING) { - log(callingSetting, targetPkgSetting, "queries component"); + synchronized (mLock) { + if (mQueriesViaComponent.contains(callingAppId, targetAppId)) { + if (DEBUG_LOGGING) { + log(callingSetting, targetPkgSetting, "queries component"); + } + return false; } - return false; } } finally { if (DEBUG_TRACING) { @@ -1597,11 +1626,13 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mImplicitlyQueryable"); } final int targetUid = UserHandle.getUid(targetUserId, targetAppId); - if (mImplicitlyQueryable.contains(callingUid, targetUid)) { - if (DEBUG_LOGGING) { - log(callingSetting, targetPkgSetting, "implicitly queryable for user"); + synchronized (mLock) { + if (mImplicitlyQueryable.contains(callingUid, targetUid)) { + if (DEBUG_LOGGING) { + log(callingSetting, targetPkgSetting, "implicitly queryable for user"); + } + return false; } - return false; } } finally { if (DEBUG_TRACING) { @@ -1614,12 +1645,14 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mRetainedImplicitlyQueryable"); } final int targetUid = UserHandle.getUid(targetUserId, targetAppId); - if (mRetainedImplicitlyQueryable.contains(callingUid, targetUid)) { - if (DEBUG_LOGGING) { - log(callingSetting, targetPkgSetting, - "retained implicitly queryable for user"); + synchronized (mLock) { + if (mRetainedImplicitlyQueryable.contains(callingUid, targetUid)) { + if (DEBUG_LOGGING) { + log(callingSetting, targetPkgSetting, + "retained implicitly queryable for user"); + } + return false; } - return false; } } finally { if (DEBUG_TRACING) { @@ -1632,7 +1665,7 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mOverlayReferenceMapper"); } final String targetName = targetPkg.getPackageName(); - if (callingSharedPkgSettings != null) { + if (!callingSharedPkgSettings.isEmpty()) { int size = callingSharedPkgSettings.size(); for (int index = 0; index < size; index++) { PackageStateInternal pkgSetting = callingSharedPkgSettings.valueAt(index); @@ -1665,11 +1698,13 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable if (DEBUG_TRACING) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mQueryableViaUsesLibrary"); } - if (mQueryableViaUsesLibrary.contains(callingAppId, targetAppId)) { - if (DEBUG_LOGGING) { - log(callingSetting, targetPkgSetting, "queryable for library users"); + synchronized (mLock) { + if (mQueryableViaUsesLibrary.contains(callingAppId, targetAppId)) { + if (DEBUG_LOGGING) { + log(callingSetting, targetPkgSetting, "queryable for library users"); + } + return false; } - return false; } } finally { if (DEBUG_TRACING) { @@ -1785,23 +1820,25 @@ public class AppsFilterImpl implements AppsFilterSnapshot, Watchable, Snappable pw.println(" system apps queryable: " + mSystemAppsQueryable); dumpPackageSet(pw, filteringAppId, mForceQueryable.untrackedStorage(), "forceQueryable", " ", expandPackages); - pw.println(" queries via package name:"); - dumpQueriesMap(pw, filteringAppId, mQueriesViaPackage, " ", expandPackages); - pw.println(" queries via component:"); - dumpQueriesMap(pw, filteringAppId, mQueriesViaComponent, " ", expandPackages); - pw.println(" queryable via interaction:"); - for (int user : users) { - pw.append(" User ").append(Integer.toString(user)).println(":"); - dumpQueriesMap(pw, - filteringAppId == null ? null : UserHandle.getUid(user, filteringAppId), - mImplicitlyQueryable, " ", expandPackages); - dumpQueriesMap(pw, - filteringAppId == null ? null : UserHandle.getUid(user, filteringAppId), - mRetainedImplicitlyQueryable, " ", expandPackages); - } - pw.println(" queryable via uses-library:"); - dumpQueriesMap(pw, filteringAppId, mQueryableViaUsesLibrary, " ", - expandPackages); + synchronized (mLock) { + pw.println(" queries via package name:"); + dumpQueriesMap(pw, filteringAppId, mQueriesViaPackage, " ", expandPackages); + pw.println(" queries via component:"); + dumpQueriesMap(pw, filteringAppId, mQueriesViaComponent, " ", expandPackages); + pw.println(" queryable via interaction:"); + for (int user : users) { + pw.append(" User ").append(Integer.toString(user)).println(":"); + dumpQueriesMap(pw, + filteringAppId == null ? null : UserHandle.getUid(user, filteringAppId), + mImplicitlyQueryable, " ", expandPackages); + dumpQueriesMap(pw, + filteringAppId == null ? null : UserHandle.getUid(user, filteringAppId), + mRetainedImplicitlyQueryable, " ", expandPackages); + } + pw.println(" queryable via uses-library:"); + dumpQueriesMap(pw, filteringAppId, mQueryableViaUsesLibrary, " ", + expandPackages); + } } private static void dumpQueriesMap(PrintWriter pw, @Nullable Integer filteringId, diff --git a/services/core/java/com/android/server/pm/ChangedPackagesTracker.java b/services/core/java/com/android/server/pm/ChangedPackagesTracker.java index bd12981bfced..380213576b2f 100644 --- a/services/core/java/com/android/server/pm/ChangedPackagesTracker.java +++ b/services/core/java/com/android/server/pm/ChangedPackagesTracker.java @@ -90,25 +90,27 @@ class ChangedPackagesTracker { } void updateSequenceNumber(@NonNull String packageName, int[] userList) { - for (int i = userList.length - 1; i >= 0; --i) { - final int userId = userList[i]; - SparseArray<String> changedPackages = mUserIdToSequenceToPackage.get(userId); - if (changedPackages == null) { - changedPackages = new SparseArray<>(); - mUserIdToSequenceToPackage.put(userId, changedPackages); - } - Map<String, Integer> sequenceNumbers = mChangedPackagesSequenceNumbers.get(userId); - if (sequenceNumbers == null) { - sequenceNumbers = new HashMap<>(); - mChangedPackagesSequenceNumbers.put(userId, sequenceNumbers); - } - final Integer sequenceNumber = sequenceNumbers.get(packageName); - if (sequenceNumber != null) { - changedPackages.remove(sequenceNumber); + synchronized (mLock) { + for (int i = userList.length - 1; i >= 0; --i) { + final int userId = userList[i]; + SparseArray<String> changedPackages = mUserIdToSequenceToPackage.get(userId); + if (changedPackages == null) { + changedPackages = new SparseArray<>(); + mUserIdToSequenceToPackage.put(userId, changedPackages); + } + Map<String, Integer> sequenceNumbers = mChangedPackagesSequenceNumbers.get(userId); + if (sequenceNumbers == null) { + sequenceNumbers = new HashMap<>(); + mChangedPackagesSequenceNumbers.put(userId, sequenceNumbers); + } + final Integer sequenceNumber = sequenceNumbers.get(packageName); + if (sequenceNumber != null) { + changedPackages.remove(sequenceNumber); + } + changedPackages.put(mChangedPackagesSequenceNumber, packageName); + sequenceNumbers.put(packageName, mChangedPackagesSequenceNumber); } - changedPackages.put(mChangedPackagesSequenceNumber, packageName); - sequenceNumbers.put(packageName, mChangedPackagesSequenceNumber); + mChangedPackagesSequenceNumber++; } - mChangedPackagesSequenceNumber++; } } diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java index 7dae22a44cc5..d3d291ea52ac 100644 --- a/services/core/java/com/android/server/pm/DeletePackageHelper.java +++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java @@ -108,7 +108,7 @@ final class DeletePackageHelper { } /** - * This method is an internal method that could be get invoked either + * This method is an internal method that could be invoked either * to delete an installed package or to clean up a failed installation. * After deleting an installed package, a broadcast is sent to notify any * listeners that the package has been removed. For cleaning up a failed @@ -146,6 +146,8 @@ final class DeletePackageHelper { int[] allUsers; final int freezeUser; final SparseArray<TempUserState> priorUserStates; + + final boolean isInstallerPackage; /** enabled state of the uninstalled application */ synchronized (mPm.mLock) { final Computer computer = mPm.snapshotComputer(); @@ -226,6 +228,8 @@ final class DeletePackageHelper { freezeUser = removeUser; priorUserStates = null; } + + isInstallerPackage = mPm.mSettings.isInstallerPackage(packageName); } synchronized (mPm.mInstallLock) { @@ -324,6 +328,12 @@ final class DeletePackageHelper { } } + if (res && isInstallerPackage) { + final PackageInstallerService packageInstallerService = + mPm.mInjector.getPackageInstallerService(); + packageInstallerService.onInstallerPackageDeleted(uninstalledPs.getAppId(), removeUser); + } + return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR; } diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 77d37dc377a2..bbdb7ebfe887 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -266,8 +266,11 @@ final class InstallPackageHelper { // Prune unused SharedUserSetting if (mPm.mSettings.checkAndPruneSharedUserLPw(requestSharedUserSetting, false)) { // Set the app ID in removed info for UID_REMOVED broadcasts - reconciledPkg.mInstallResult.mRemovedInfo.mRemovedAppId = - requestSharedUserSetting.mAppId; + if (reconciledPkg.mInstallResult != null + && reconciledPkg.mInstallResult.mRemovedInfo != null) { + reconciledPkg.mInstallResult.mRemovedInfo.mRemovedAppId = + requestSharedUserSetting.mAppId; + } } } } diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 9b5984e09c8b..e406a1a4bca7 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -861,6 +861,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements synchronized (mSessions) { mSessions.put(sessionId, session); } + mPm.addInstallerPackageName(session.getInstallSource()); mCallbacks.notifySessionCreated(session.sessionId, session.userId); @@ -1735,4 +1736,37 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements .setPackage(sessionInfo.installerPackageName); mContext.sendBroadcastAsUser(sessionUpdatedIntent, UserHandle.of(userId)); } + + /** + * Abandon unfinished sessions if the installer package has been uninstalled. + * @param installerAppId the app ID of the installer package that has been uninstalled. + * @param userId the user that has the installer package uninstalled. + */ + void onInstallerPackageDeleted(int installerAppId, int userId) { + synchronized (mSessions) { + for (int i = 0; i < mSessions.size(); i++) { + final PackageInstallerSession session = mSessions.valueAt(i); + if (!matchesInstaller(session, installerAppId, userId)) { + continue; + } + // Find parent session and only abandon parent session if installer matches + PackageInstallerSession root = !session.hasParentSessionId() + ? session : mSessions.get(session.getParentSessionId()); + if (root != null && matchesInstaller(root, installerAppId, userId) + && !root.isDestroyed()) { + root.abandon(); + } + } + } + } + + private boolean matchesInstaller(PackageInstallerSession session, int installerAppId, + int userId) { + final int installerUid = session.getInstallerUid(); + if (installerAppId == UserHandle.USER_ALL) { + return UserHandle.getAppId(installerUid) == installerAppId; + } else { + return UserHandle.getUid(userId, installerAppId) == installerUid; + } + } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index e1af9a7ab96f..ffd924edc7d8 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -1543,6 +1543,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService } // Link watchables to the class + @SuppressWarnings("GuardedBy") private void registerObservers(boolean verify) { // Null check to handle nullable test parameters if (mPackages != null) { @@ -2256,7 +2257,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService @GuardedBy("mLock") void updateInstantAppInstallerLocked(String modifiedPackage) { - // we're only interested in updating the installer appliction when 1) it's not + // we're only interested in updating the installer application when 1) it's not // already set or 2) the modified package is the installer if (mInstantAppInstallerActivity != null && !mInstantAppInstallerActivity.getComponentName().getPackageName() @@ -2740,7 +2741,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService return mModuleInfoProvider.getModuleInfo(packageName, flags); } - @GuardedBy("mLock") void updateSequenceNumberLP(PackageSetting pkgSetting, int[] userList) { mChangedPackagesTracker.updateSequenceNumber(pkgSetting.getPackageName(), userList); } @@ -2877,8 +2877,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService synchronized (mLock) { mPackageUsage.writeNow(mSettings.getPackagesLocked()); - if (mHandler.hasMessages(WRITE_SETTINGS)) { - mHandler.removeMessages(WRITE_SETTINGS); + if (mHandler.hasMessages(WRITE_SETTINGS) + || mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS) + || mHandler.hasMessages(WRITE_PACKAGE_LIST)) { writeSettings(); } } @@ -3073,8 +3074,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService userId); } - private void enforceCanSetDistractingPackageRestrictionsAsUser(@NonNull Computer snapshot, - int callingUid, int userId, String callingMethod) { + private void enforceCanSetDistractingPackageRestrictionsAsUser(int callingUid, int userId, + String callingMethod) { mContext.enforceCallingOrSelfPermission(Manifest.permission.SUSPEND_APPS, callingMethod); @@ -3158,6 +3159,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService } } + @SuppressWarnings("GuardedBy") VersionInfo getSettingsVersionForPackage(AndroidPackage pkg) { if (pkg.isExternalStorage()) { if (TextUtils.isEmpty(pkg.getVolumeUuid())) { @@ -3287,6 +3289,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService * Update component enabled settings to {@link PackageManager#COMPONENT_ENABLED_STATE_DEFAULT} * if the resetEnabledSettingsOnAppDataCleared is {@code true}. */ + @GuardedBy("mLock") private void resetComponentEnabledSettingsIfNeededLPw(String packageName, int userId) { final AndroidPackage pkg = packageName != null ? mPackages.get(packageName) : null; if (pkg == null || !pkg.isResetEnabledSettingsOnAppDataCleared()) { @@ -3878,6 +3881,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService } } + @GuardedBy("mLock") private boolean setEnabledSettingInternalLocked(@NonNull Computer computer, PackageSetting pkgSetting, ComponentEnabledSetting setting, @UserIdInt int userId, String callingPackage) { @@ -4553,7 +4557,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService final Computer snapshot = snapshotComputer(); unsuspendForSuspendingPackage(snapshot, packageName, userId); removeAllDistractingPackageRestrictions(snapshot, userId); - flushPackageRestrictionsAsUserInternalLocked(userId); + synchronized (mLock) { + flushPackageRestrictionsAsUserInternalLocked(userId); + } } } if (observer != null) { @@ -4971,6 +4977,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override + @SuppressWarnings("GuardedBy") public int getRuntimePermissionsVersion(@UserIdInt int userId) { Preconditions.checkArgumentNonnegative(userId); enforceAdjustRuntimePermissionsPolicyOrUpgradeRuntimePermissions( @@ -5575,7 +5582,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService int restrictionFlags, int userId) { final int callingUid = Binder.getCallingUid(); final Computer snapshot = snapshotComputer(); - enforceCanSetDistractingPackageRestrictionsAsUser(snapshot, callingUid, userId, + enforceCanSetDistractingPackageRestrictionsAsUser(callingUid, userId, "setDistractingPackageRestrictionsAsUser"); Objects.requireNonNull(packageNames, "packageNames cannot be null"); return mDistractingPackageHelper.setDistractingPackageRestrictionsAsUser(snapshot, @@ -5844,6 +5851,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override + @SuppressWarnings("GuardedBy") public void setRuntimePermissionsVersion(int version, @UserIdInt int userId) { Preconditions.checkArgumentNonnegative(version); Preconditions.checkArgumentNonnegative(userId); @@ -6362,6 +6370,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override + @SuppressWarnings("GuardedBy") public void updateRuntimePermissionsFingerprint(@UserIdInt int userId) { mSettings.updateRuntimePermissionsFingerprint(userId); } @@ -6396,6 +6405,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService } @Override + @SuppressWarnings("GuardedBy") public boolean isPermissionUpgradeNeeded(int userId) { return mSettings.isPermissionUpgradeNeeded(userId); } @@ -7167,4 +7177,10 @@ public class PackageManagerService implements PackageSender, TestUtilityService void notifyInstantAppPackageInstalled(String packageName, int[] newUsers) { mInstantAppRegistry.onPackageInstalled(snapshotComputer(), packageName, newUsers); } + + void addInstallerPackageName(InstallSource installSource) { + synchronized (mLock) { + mSettings.addInstallerPackageNames(installSource); + } + } } diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index d6ab78bd27ea..7b0659332412 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -17,6 +17,11 @@ package com.android.server.pm; import static android.content.pm.PackageInstaller.LOCATION_DATA_APP; +import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; +import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT; +import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED; +import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED; +import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET; import android.accounts.IAccountManager; import android.annotation.NonNull; @@ -92,6 +97,7 @@ import android.system.ErrnoException; import android.system.Os; import android.text.TextUtils; import android.text.format.DateUtils; +import android.util.ArrayMap; import android.util.ArraySet; import android.util.IntArray; import android.util.PrintWriterPrinter; @@ -150,6 +156,17 @@ class PackageManagerShellCommand extends ShellCommand { "--multi-package" ); private static final Set<String> UNSUPPORTED_SESSION_CREATE_OPTS = Collections.emptySet(); + private static final Map<String, Integer> SUPPORTED_PERMISSION_FLAGS = new ArrayMap<>(); + private static final List<String> SUPPORTED_PERMISSION_FLAGS_LIST; + static { + SUPPORTED_PERMISSION_FLAGS.put("user-set", FLAG_PERMISSION_USER_SET); + SUPPORTED_PERMISSION_FLAGS.put("user-fixed", FLAG_PERMISSION_USER_FIXED); + SUPPORTED_PERMISSION_FLAGS.put("revoked-compat", FLAG_PERMISSION_REVOKED_COMPAT); + SUPPORTED_PERMISSION_FLAGS.put("review-required", FLAG_PERMISSION_REVIEW_REQUIRED); + SUPPORTED_PERMISSION_FLAGS.put("revoke-when-requested", + FLAG_PERMISSION_REVOKE_WHEN_REQUESTED); + SUPPORTED_PERMISSION_FLAGS_LIST = new ArrayList<>(SUPPORTED_PERMISSION_FLAGS.keySet()); + } final IPackageManager mInterface; final LegacyPermissionManagerInternal mLegacyPermissionManager; @@ -276,6 +293,10 @@ class PackageManagerShellCommand extends ShellCommand { return runGrantRevokePermission(false); case "reset-permissions": return runResetPermissions(); + case "set-permission-flags": + return setOrClearPermissionFlags(true); + case "clear-permission-flags": + return setOrClearPermissionFlags(false); case "set-permission-enforced": return runSetPermissionEnforced(); case "get-privapp-permissions": @@ -2500,6 +2521,50 @@ class PackageManagerShellCommand extends ShellCommand { return 0; } + private int setOrClearPermissionFlags(boolean setFlags) { + int userId = UserHandle.USER_SYSTEM; + + String opt; + while ((opt = getNextOption()) != null) { + if (opt.equals("--user")) { + userId = UserHandle.parseUserArg(getNextArgRequired()); + } + } + + String pkg = getNextArg(); + if (pkg == null) { + getErrPrintWriter().println("Error: no package specified"); + return 1; + } + String perm = getNextArg(); + if (perm == null) { + getErrPrintWriter().println("Error: no permission specified"); + return 1; + } + + int flagMask = 0; + String flagName = getNextArg(); + if (flagName == null) { + getErrPrintWriter().println("Error: no permission flags specified"); + return 1; + } + while (flagName != null) { + if (!SUPPORTED_PERMISSION_FLAGS.containsKey(flagName)) { + getErrPrintWriter().println("Error: specified flag " + flagName + " is not one of " + + SUPPORTED_PERMISSION_FLAGS_LIST); + return 1; + } + flagMask |= SUPPORTED_PERMISSION_FLAGS.get(flagName); + flagName = getNextArg(); + } + + final UserHandle translatedUser = UserHandle.of(translateUserId(userId, + UserHandle.USER_NULL, "runGrantRevokePermission")); + int flagSet = setFlags ? flagMask : 0; + mPermissionManager.updatePermissionFlags(pkg, perm, flagMask, flagSet, translatedUser); + return 0; + } + private int runSetPermissionEnforced() throws RemoteException { final String permission = getNextArg(); if (permission == null) { @@ -3997,6 +4062,13 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" must be declared as used in the app's manifest, be runtime permissions"); pw.println(" (protection level dangerous), and the app targeting SDK greater than Lollipop MR1."); pw.println(""); + pw.println(" set-permission-flags [--user USER_ID] PACKAGE PERMISSION [FLAGS..]"); + pw.println(" clear-permission-flags [--user USER_ID] PACKAGE PERMISSION [FLAGS..]"); + pw.println(" These commands either set or clear permission flags on apps. The permissions"); + pw.println(" must be declared as used in the app's manifest, be runtime permissions"); + pw.println(" (protection level dangerous), and the app targeting SDK greater than Lollipop MR1."); + pw.println(" The flags must be one or more of " + SUPPORTED_PERMISSION_FLAGS_LIST); + pw.println(""); pw.println(" reset-permissions"); pw.println(" Revert all runtime permissions to their default state."); pw.println(""); diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index b53cfc558f6e..e6d59d43ffbe 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -380,8 +380,8 @@ public final class Settings implements Watchable, Snappable { private final SnapshotCache<WatchedArrayMap<String, PackageSetting>> mPackagesSnapshot; /** - * List of packages that were involved in installing other packages, i.e. are listed - * in at least one app's InstallSource. + * List of packages that were involved in installing other packages, i.e. packages that created + * new sessions or are listed in at least one app's InstallSource. */ @Watched private final WatchedArraySet<String> mInstallerPackages; @@ -5923,4 +5923,8 @@ public final class Settings implements Watchable, Snappable { } } } + + boolean isInstallerPackage(@NonNull String packageName) { + return mInstallerPackages.contains(packageName); + } } diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index 056f25542294..9627c4394db7 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -105,6 +105,7 @@ import android.util.TypedXmlSerializer; import android.util.Xml; import android.view.IWindowManager; +import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; @@ -455,6 +456,8 @@ public class ShortcutService extends IShortcutService.Stub { private final boolean mIsAppSearchEnabled; + private ComponentName mChooserActivity; + static class InvalidFileFormatException extends Exception { public InvalidFileFormatException(String message, Throwable cause) { super(message, cause); @@ -1646,6 +1649,26 @@ public class ShortcutService extends IShortcutService.Stub { return callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID; } + @VisibleForTesting + ComponentName injectChooserActivity() { + if (mChooserActivity == null) { + mChooserActivity = ComponentName.unflattenFromString( + mContext.getResources().getString(R.string.config_chooserActivity)); + } + return mChooserActivity; + } + + private boolean isCallerChooserActivity() { + // TODO(b/228975502): Migrate this check to a proper permission or role check + final int callingUid = injectBinderCallingUid(); + ComponentName systemChooser = injectChooserActivity(); + if (systemChooser == null) { + return false; + } + int uid = injectGetPackageUid(systemChooser.getPackageName(), UserHandle.USER_SYSTEM); + return uid == callingUid; + } + private void enforceSystemOrShell() { if (!(isCallerSystem() || isCallerShell())) { throw new SecurityException("Caller must be system or shell"); @@ -2525,7 +2548,9 @@ public class ShortcutService extends IShortcutService.Stub { IntentFilter filter, @UserIdInt int userId) { Preconditions.checkStringNotEmpty(packageName, "packageName"); Objects.requireNonNull(filter, "intentFilter"); - verifyCaller(packageName, userId); + if (!isCallerChooserActivity()) { + verifyCaller(packageName, userId); + } enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APP_PREDICTIONS, "getShareTargets"); synchronized (mLock) { diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java index 0e6d5e5ed463..8dc94287688d 100644 --- a/services/core/java/com/android/server/pm/UserManagerInternal.java +++ b/services/core/java/com/android/server/pm/UserManagerInternal.java @@ -92,21 +92,6 @@ public abstract class UserManagerInternal { public abstract void setDevicePolicyUserRestrictions(int originatingUserId, @Nullable Bundle global, @Nullable RestrictionsSet local, boolean isDeviceOwner); - /** - * Returns the "base" user restrictions. - * - * Used by {@link com.android.server.devicepolicy.DevicePolicyManagerService} for upgrading - * from MNC. - */ - public abstract Bundle getBaseUserRestrictions(int userId); - - /** - * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} for upgrading - * from MNC. - */ - public abstract void setBaseUserRestrictionsByDpmsForMigration(int userId, - Bundle baseRestrictions); - /** Return a user restriction. */ public abstract boolean getUserRestriction(int userId, String key); diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index ee0fdc07f841..358e71a70550 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -4317,16 +4317,9 @@ public class UserManagerService extends IUserManager.Stub { private long logUserCreateJourneyBegin(@UserIdInt int userId, String userType, @UserInfoFlag int flags) { - final long sessionId = ThreadLocalRandom.current().nextLong(1, Long.MAX_VALUE); - // log the journey atom with the user metadata - FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED, sessionId, + return logUserJourneyBegin( FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_CREATE, - /* origin_user= */ -1, userId, UserManager.getUserTypeForStatsd(userType), flags); - // log the event atom to indicate the event start - FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED, sessionId, userId, - FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__CREATE_USER, - FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__BEGIN); - return sessionId; + userId, userType, flags); } private void logUserCreateJourneyFinish(long sessionId, @UserIdInt int userId, boolean finish) { @@ -4336,6 +4329,46 @@ public class UserManagerService extends IUserManager.Stub { : FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__NONE); } + private long logUserRemoveJourneyBegin(@UserIdInt int userId, String userType, + @UserInfoFlag int flags) { + return logUserJourneyBegin( + FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_REMOVE, + userId, userType, flags); + } + + private void logUserRemoveJourneyFinish(long sessionId, @UserIdInt int userId, boolean finish) { + FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED, sessionId, userId, + FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__REMOVE_USER, + finish ? FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__FINISH + : FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__NONE); + } + + private long logUserJourneyBegin(int journey, @UserIdInt int userId, String userType, + @UserInfoFlag int flags) { + final long sessionId = ThreadLocalRandom.current().nextLong(1, Long.MAX_VALUE); + // log the journey atom with the user metadata + FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED, sessionId, + journey, /* origin_user= */ -1, userId, + UserManager.getUserTypeForStatsd(userType), flags); + + // log the event atom to indicate the event start + int event; + switch (journey) { + case FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_CREATE: + event = FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__CREATE_USER; + break; + case FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_REMOVE: + event = FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__REMOVE_USER; + break; + default: + throw new IllegalArgumentException("Journey " + journey + " not expected."); + } + + FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED, sessionId, userId, + event, FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__BEGIN); + return sessionId; + } + /** Register callbacks for statsd pulled atoms. */ private void registerStatsCallbacks() { final StatsManager statsManager = mContext.getSystemService(StatsManager.class); @@ -4578,6 +4611,10 @@ public class UserManagerService extends IUserManager.Stub { userData.info.flags |= UserInfo.FLAG_DISABLED; writeUserLP(userData); } + + final long sessionId = logUserRemoveJourneyBegin( + userId, userData.info.userType, userData.info.flags); + try { mAppOpsService.removeUser(userId); } catch (RemoteException e) { @@ -4600,9 +4637,11 @@ public class UserManagerService extends IUserManager.Stub { @Override public void userStopped(int userIdParam) { finishRemoveUser(userIdParam); + logUserRemoveJourneyFinish(sessionId, userIdParam, true); } @Override public void userStopAborted(int userIdParam) { + logUserRemoveJourneyFinish(sessionId, userIdParam, false); } }); } catch (RemoteException e) { @@ -5861,33 +5900,6 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public Bundle getBaseUserRestrictions(@UserIdInt int userId) { - synchronized (mRestrictionsLock) { - return mBaseUserRestrictions.getRestrictions(userId); - } - } - - @Override - public void setBaseUserRestrictionsByDpmsForMigration( - @UserIdInt int userId, Bundle baseRestrictions) { - synchronized (mRestrictionsLock) { - if (mBaseUserRestrictions.updateRestrictions(userId, - new Bundle(baseRestrictions))) { - invalidateEffectiveUserRestrictionsLR(userId); - } - } - - final UserData userData = getUserDataNoChecks(userId); - synchronized (mPackagesLock) { - if (userData != null) { - writeUserLP(userData); - } else { - Slog.w(LOG_TAG, "UserInfo not found for " + userId); - } - } - } - - @Override public boolean getUserRestriction(@UserIdInt int userId, String key) { return getUserRestrictions(userId).getBoolean(key); } diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java index 849f53026c99..349174d95ec4 100644 --- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java @@ -207,6 +207,9 @@ final class DefaultPermissionGrantPolicy { STORAGE_PERMISSIONS.add(Manifest.permission.READ_EXTERNAL_STORAGE); STORAGE_PERMISSIONS.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); STORAGE_PERMISSIONS.add(Manifest.permission.ACCESS_MEDIA_LOCATION); + STORAGE_PERMISSIONS.add(Manifest.permission.READ_MEDIA_AUDIO); + STORAGE_PERMISSIONS.add(Manifest.permission.READ_MEDIA_VIDEO); + STORAGE_PERMISSIONS.add(Manifest.permission.READ_MEDIA_IMAGES); } private static final Set<String> NEARBY_DEVICES_PERMISSIONS = new ArraySet<>(); diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java index c524fb7ae9e5..186eccc80f8a 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java @@ -223,6 +223,9 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt STORAGE_PERMISSIONS.add(Manifest.permission.READ_EXTERNAL_STORAGE); STORAGE_PERMISSIONS.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); STORAGE_PERMISSIONS.add(Manifest.permission.ACCESS_MEDIA_LOCATION); + STORAGE_PERMISSIONS.add(Manifest.permission.READ_MEDIA_AUDIO); + STORAGE_PERMISSIONS.add(Manifest.permission.READ_MEDIA_IMAGES); + STORAGE_PERMISSIONS.add(Manifest.permission.READ_MEDIA_VIDEO); NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.BLUETOOTH_ADVERTISE); NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.BLUETOOTH_CONNECT); NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.BLUETOOTH_SCAN); @@ -297,6 +300,8 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt .OnRuntimePermissionStateChangedListener> mRuntimePermissionStateChangedListeners = new ArrayList<>(); + private final boolean mIsLeanback; + @NonNull private final OnPermissionChangeListeners mOnPermissionChangeListeners; @@ -380,6 +385,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt mContext = context; mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class); mUserManagerInt = LocalServices.getService(UserManagerInternal.class); + mIsLeanback = availableFeatures.containsKey(PackageManager.FEATURE_LEANBACK); mPrivilegedPermissionAllowlistSourcePackageNames.add(PLATFORM_PACKAGE_NAME); // PackageManager.hasSystemFeature() is not used here because PackageManagerService @@ -761,8 +767,10 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt flagValues &= ~FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT; flagValues &= ~FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT; flagValues &= ~PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION; - // REVIEW_REQUIRED can only be set by non-system apps for for POST_NOTIFICATIONS - if (!POST_NOTIFICATIONS.equals(permName)) { + // REVIEW_REQUIRED can only be set by non-system apps for POST_NOTIFICATIONS, or by the + // shell or root UID. + if (!POST_NOTIFICATIONS.equals(permName) && callingUid != Process.SHELL_UID + && callingUid != Process.ROOT_UID) { flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; } } @@ -2822,6 +2830,14 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt } } } + if (mIsLeanback && NOTIFICATION_PERMISSIONS.contains(permName)) { + uidState.grantPermission(bp); + if (origPermState == null || !origPermState.isGranted()) { + if (uidState.grantPermission(bp)) { + wasChanged = true; + } + } + } } else { if (origPermState == null) { // New permission diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java index 9aa53f18d0aa..7baec6217e2e 100644 --- a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java +++ b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java @@ -79,7 +79,8 @@ import java.util.Set; import java.util.function.Function; /** Resolves all Android component types [activities, services, providers and receivers]. */ -public class ComponentResolver extends ComponentResolverLocked implements Snappable { +public class ComponentResolver extends ComponentResolverLocked implements + Snappable<ComponentResolverApi> { private static final boolean DEBUG = false; private static final String TAG = "PackageManager"; private static final boolean DEBUG_FILTERS = false; @@ -166,11 +167,13 @@ public class ComponentResolver extends ComponentResolverLocked implements Snappa mProvidersByAuthority = new ArrayMap<>(); mDeferProtectedFilters = true; - mSnapshot = new SnapshotCache<ComponentResolverApi>(this, this) { + mSnapshot = new SnapshotCache<>(this, this) { @Override public ComponentResolverApi createSnapshot() { - return new ComponentResolverSnapshot(ComponentResolver.this, - userNeedsBadgingCache); + synchronized (mLock) { + return new ComponentResolverSnapshot(ComponentResolver.this, + userNeedsBadgingCache); + } }}; } diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java index e8546a768429..32e7a6a81096 100644 --- a/services/core/java/com/android/server/policy/PermissionPolicyService.java +++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java @@ -59,6 +59,8 @@ import android.content.pm.PackageManagerInternal.PackageListObserver; import android.content.pm.PermissionInfo; import android.os.Build; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; @@ -160,11 +162,13 @@ public final class PermissionPolicyService extends SystemService { private NotificationManagerInternal mNotificationManager; private final KeyguardManager mKeyguardManager; private final PackageManager mPackageManager; + private final Handler mHandler; public PermissionPolicyService(@NonNull Context context) { super(context); mContext = context; + mHandler = new Handler(Looper.getMainLooper()); mPackageManager = context.getPackageManager(); mKeyguardManager = context.getSystemService(KeyguardManager.class); LocalServices.addService(PermissionPolicyInternal.class, new Internal()); @@ -1068,8 +1072,11 @@ public final class PermissionPolicyService extends SystemService { activityInfo.packageName, user)) { clearNotificationReviewFlagsIfNeeded(activityInfo.packageName, user); } else { - showNotificationPromptIfNeeded(activityInfo.packageName, - taskInfo.userId, taskInfo.taskId, info); + // Post the activity start checks to ensure the notification channel + // checks happen outside the WindowManager global lock. + mHandler.post(() -> showNotificationPromptIfNeeded( + activityInfo.packageName, taskInfo.userId, taskInfo.taskId, + info)); } } }; diff --git a/services/core/java/com/android/server/policy/SideFpsEventHandler.java b/services/core/java/com/android/server/policy/SideFpsEventHandler.java index f36869859170..41d02727d9eb 100644 --- a/services/core/java/com/android/server/policy/SideFpsEventHandler.java +++ b/services/core/java/com/android/server/policy/SideFpsEventHandler.java @@ -16,9 +16,9 @@ package com.android.server.policy; -import static android.hardware.fingerprint.FingerprintStateListener.STATE_BP_AUTH; -import static android.hardware.fingerprint.FingerprintStateListener.STATE_ENROLLING; -import static android.hardware.fingerprint.FingerprintStateListener.STATE_IDLE; +import static android.hardware.biometrics.BiometricStateListener.STATE_BP_AUTH; +import static android.hardware.biometrics.BiometricStateListener.STATE_ENROLLING; +import static android.hardware.biometrics.BiometricStateListener.STATE_IDLE; import android.annotation.NonNull; import android.annotation.Nullable; @@ -30,9 +30,9 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; +import android.hardware.biometrics.BiometricStateListener; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; -import android.hardware.fingerprint.FingerprintStateListener; import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback; import android.os.Handler; import android.os.PowerManager; @@ -67,7 +67,7 @@ public class SideFpsEventHandler { } }; - private @FingerprintStateListener.State int mFingerprintState; + private @BiometricStateListener.State int mBiometricState; SideFpsEventHandler(Context context, Handler handler, PowerManager powerManager) { this(context, handler, powerManager, () -> new AlertDialog.Builder(context)); @@ -80,7 +80,7 @@ public class SideFpsEventHandler { mHandler = handler; mPowerManager = powerManager; mDialogSupplier = dialogSupplier; - mFingerprintState = STATE_IDLE; + mBiometricState = STATE_IDLE; mSideFpsEventHandlerReady = new AtomicBoolean(false); // ensure dialog is dismissed if screen goes off for unrelated reasons @@ -108,7 +108,7 @@ public class SideFpsEventHandler { return false; } - switch (mFingerprintState) { + switch (mBiometricState) { case STATE_ENROLLING: case STATE_BP_AUTH: mHandler.post(() -> { @@ -116,7 +116,7 @@ public class SideFpsEventHandler { mDialog.dismiss(); } mDialog = showConfirmDialog(mDialogSupplier.get(), - mPowerManager, eventTime, mFingerprintState, mDialogDismissListener); + mPowerManager, eventTime, mBiometricState, mDialogDismissListener); }); return true; default: @@ -127,9 +127,9 @@ public class SideFpsEventHandler { @NonNull private static Dialog showConfirmDialog(@NonNull AlertDialog.Builder dialogBuilder, @NonNull PowerManager powerManager, long eventTime, - @FingerprintStateListener.State int fingerprintState, + @BiometricStateListener.State int biometricState, @NonNull DialogInterface.OnDismissListener dismissListener) { - final boolean enrolling = fingerprintState == STATE_ENROLLING; + final boolean enrolling = biometricState == STATE_ENROLLING; final int title = enrolling ? R.string.fp_power_button_enrollment_title : R.string.fp_power_button_bp_title; final int message = enrolling ? R.string.fp_power_button_enrollment_message @@ -165,8 +165,8 @@ public class SideFpsEventHandler { /** * Awaits notification from PhoneWindowManager that fingerprint service is ready * to send updates about power button fps sensor state. Then configures a - * FingerprintStateListener to receive and record updates to fps state, and - * registers the FingerprintStateListener in FingerprintManager. + * BiometricStateListener to receive and record updates to fps state, and + * registers the BiometricStateListener in FingerprintManager. */ public void onFingerprintSensorReady() { final PackageManager pm = mContext.getPackageManager(); @@ -182,13 +182,14 @@ public class SideFpsEventHandler { public void onAllAuthenticatorsRegistered( List<FingerprintSensorPropertiesInternal> sensors) { if (fingerprintManager.isPowerbuttonFps()) { - fingerprintManager.registerFingerprintStateListener( - new FingerprintStateListener() { - @Nullable private Runnable mStateRunnable = null; + fingerprintManager.registerBiometricStateListener( + new BiometricStateListener() { + @Nullable + private Runnable mStateRunnable = null; @Override public void onStateChanged( - @FingerprintStateListener.State int newState) { + @BiometricStateListener.State int newState) { if (mStateRunnable != null) { mHandler.removeCallbacks(mStateRunnable); mStateRunnable = null; @@ -198,11 +199,11 @@ public class SideFpsEventHandler { // arrive in any order (success auth & power). Add a // damper when moving to idle in case auth is first if (newState == STATE_IDLE) { - mStateRunnable = () -> mFingerprintState = newState; + mStateRunnable = () -> mBiometricState = newState; mHandler.postDelayed(mStateRunnable, DEBOUNCE_DELAY_MILLIS); } else { - mFingerprintState = newState; + mBiometricState = newState; } } }); diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java index aede4b1e2f5d..685b744c8062 100644 --- a/services/core/java/com/android/server/power/Notifier.java +++ b/services/core/java/com/android/server/power/Notifier.java @@ -64,6 +64,8 @@ import com.android.server.policy.WindowManagerPolicy; import com.android.server.statusbar.StatusBarManagerInternal; import java.io.PrintWriter; +import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicBoolean; /** * Sends broadcasts about important power state changes. @@ -133,6 +135,7 @@ public class Notifier { private final DisplayManagerInternal mDisplayManagerInternal; private final NotifierHandler mHandler; + private final Executor mBackgroundExecutor; private final Intent mScreenOnIntent; private final Intent mScreenOffIntent; @@ -169,9 +172,12 @@ public class Notifier { // True if a user activity message should be sent. private boolean mUserActivityPending; + private final AtomicBoolean mIsPlayingChargingStartedFeedback = new AtomicBoolean(false); + public Notifier(Looper looper, Context context, IBatteryStats batteryStats, SuspendBlocker suspendBlocker, WindowManagerPolicy policy, - FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector) { + FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector, + Executor backgroundExecutor) { mContext = context; mBatteryStats = batteryStats; mAppOps = mContext.getSystemService(AppOpsManager.class); @@ -188,6 +194,7 @@ public class Notifier { mVibrator = mContext.getSystemService(Vibrator.class); mHandler = new NotifierHandler(looper); + mBackgroundExecutor = backgroundExecutor; mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON); mScreenOnIntent.addFlags( Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND @@ -824,25 +831,36 @@ public class Notifier { return; } - // vibrate - final boolean vibrate = Settings.Secure.getIntForUser(mContext.getContentResolver(), - Settings.Secure.CHARGING_VIBRATION_ENABLED, 1, userId) != 0; - if (vibrate) { - mVibrator.vibrate(CHARGING_VIBRATION_EFFECT, HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES); + if (!mIsPlayingChargingStartedFeedback.compareAndSet(false, true)) { + // there's already a charging started feedback Runnable scheduled to run on the + // background thread, so let's not execute another + return; } - // play sound - final String soundPath = Settings.Global.getString(mContext.getContentResolver(), - wireless ? Settings.Global.WIRELESS_CHARGING_STARTED_SOUND - : Settings.Global.CHARGING_STARTED_SOUND); - final Uri soundUri = Uri.parse("file://" + soundPath); - if (soundUri != null) { - final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri); - if (sfx != null) { - sfx.setStreamType(AudioManager.STREAM_SYSTEM); - sfx.play(); + // vibrate & play sound on a background thread + mBackgroundExecutor.execute(() -> { + // vibrate + final boolean vibrate = Settings.Secure.getIntForUser(mContext.getContentResolver(), + Settings.Secure.CHARGING_VIBRATION_ENABLED, 1, userId) != 0; + if (vibrate) { + mVibrator.vibrate(CHARGING_VIBRATION_EFFECT, + HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES); } - } + + // play sound + final String soundPath = Settings.Global.getString(mContext.getContentResolver(), + wireless ? Settings.Global.WIRELESS_CHARGING_STARTED_SOUND + : Settings.Global.CHARGING_STARTED_SOUND); + final Uri soundUri = Uri.parse("file://" + soundPath); + if (soundUri != null) { + final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri); + if (sfx != null) { + sfx.setStreamType(AudioManager.STREAM_SYSTEM); + sfx.play(); + } + } + mIsPlayingChargingStartedFeedback.set(false); + }); } private void showWirelessChargingStarted(int batteryLevel, @UserIdInt int userId) { diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index ad56f199c269..e0da0e8bdf35 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -140,6 +140,7 @@ import java.util.Arrays; import java.util.List; import java.util.NoSuchElementException; import java.util.Objects; +import java.util.concurrent.Executor; /** * The power manager service is responsible for coordinating power management @@ -524,9 +525,6 @@ public final class PowerManagerService extends SystemService // The screen off timeout setting value in milliseconds. private long mScreenOffTimeoutSetting; - // The screen off timeout setting value in milliseconds to apply while device is docked. - private long mScreenOffTimeoutDockedSetting; - // Default for attentive warning duration. private long mAttentiveWarningDurationConfig; @@ -908,10 +906,11 @@ public final class PowerManagerService extends SystemService static class Injector { Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats, SuspendBlocker suspendBlocker, WindowManagerPolicy policy, - FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector) { + FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector, + Executor backgroundExecutor) { return new Notifier( looper, context, batteryStats, suspendBlocker, policy, faceDownDetector, - screenUndimDetector); + screenUndimDetector, backgroundExecutor); } SuspendBlocker createSuspendBlocker(PowerManagerService service, String name) { @@ -1230,7 +1229,8 @@ public final class PowerManagerService extends SystemService mBatteryStats = BatteryStatsService.getService(); mNotifier = mInjector.createNotifier(Looper.getMainLooper(), mContext, mBatteryStats, mInjector.createSuspendBlocker(this, "PowerManagerService.Broadcasts"), - mPolicy, mFaceDownDetector, mScreenUndimDetector); + mPolicy, mFaceDownDetector, mScreenUndimDetector, + BackgroundThread.getExecutor()); mPowerGroups.append(Display.DEFAULT_DISPLAY_GROUP, new PowerGroup(WAKEFULNESS_AWAKE, mPowerGroupWakefulnessChangeListener, @@ -1289,9 +1289,6 @@ public final class PowerManagerService extends SystemService resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.SCREEN_OFF_TIMEOUT), false, mSettingsObserver, UserHandle.USER_ALL); - resolver.registerContentObserver(Settings.System.getUriFor( - Settings.System.SCREEN_OFF_TIMEOUT_DOCKED), - false, mSettingsObserver, UserHandle.USER_ALL); resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.SLEEP_TIMEOUT), false, mSettingsObserver, UserHandle.USER_ALL); @@ -1414,9 +1411,6 @@ public final class PowerManagerService extends SystemService mScreenOffTimeoutSetting = Settings.System.getIntForUser(resolver, Settings.System.SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT, UserHandle.USER_CURRENT); - mScreenOffTimeoutDockedSetting = Settings.System.getLongForUser(resolver, - Settings.System.SCREEN_OFF_TIMEOUT_DOCKED, mScreenOffTimeoutSetting, - UserHandle.USER_CURRENT); mSleepTimeoutSetting = Settings.Secure.getIntForUser(resolver, Settings.Secure.SLEEP_TIMEOUT, DEFAULT_SLEEP_TIMEOUT, UserHandle.USER_CURRENT); @@ -2999,9 +2993,7 @@ public final class PowerManagerService extends SystemService @GuardedBy("mLock") private long getScreenOffTimeoutLocked(long sleepTimeout, long attentiveTimeout) { - long timeout = mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED - ? mScreenOffTimeoutSetting - : mScreenOffTimeoutDockedSetting; + long timeout = mScreenOffTimeoutSetting; if (isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) { timeout = Math.min(timeout, mMaximumScreenOffTimeoutFromDeviceAdmin); } @@ -4946,8 +4938,7 @@ public final class PowerManagerService extends SystemService } } - @VisibleForTesting - final class DockReceiver extends BroadcastReceiver { + private final class DockReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { synchronized (mLock) { diff --git a/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java b/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java index bce1cce0f47f..08344170b02d 100644 --- a/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java +++ b/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java @@ -560,7 +560,7 @@ public final class SensorPrivacyService extends SystemService { + " sensors"); return; } - mContext.startActivityAsUser(dialogIntent, options.toBundle(), info.mUser); + mContext.startActivityAsUser(dialogIntent, options.toBundle(), UserHandle.SYSTEM); } /** diff --git a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java index ae52912d4821..7173f6008177 100644 --- a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java +++ b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java @@ -59,6 +59,8 @@ public final class ServiceConfigAccessorImpl implements ServiceConfigAccessor { */ private static final Set<String> CONFIGURATION_INTERNAL_SERVER_FLAGS_KEYS_TO_WATCH = Set.of( ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED, + ServerFlags.KEY_PRIMARY_LTZP_MODE_OVERRIDE, + ServerFlags.KEY_SECONDARY_LTZP_MODE_OVERRIDE, ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_RUN_IN_BACKGROUND_ENABLED, ServerFlags.KEY_ENHANCED_METRICS_COLLECTION_ENABLED, ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT, @@ -443,6 +445,9 @@ public final class ServiceConfigAccessorImpl implements ServiceConfigAccessor { mTestPrimaryLocationTimeZoneProviderMode = mTestPrimaryLocationTimeZoneProviderPackageName == null ? PROVIDER_MODE_DISABLED : PROVIDER_MODE_ENABLED; + // Changing this state can affect the content of ConfigurationInternal, so listeners need to + // be informed. + mContext.getMainThreadHandler().post(this::handleConfigurationInternalChangeOnMainThread); } @Override @@ -469,6 +474,9 @@ public final class ServiceConfigAccessorImpl implements ServiceConfigAccessor { mTestSecondaryLocationTimeZoneProviderMode = mTestSecondaryLocationTimeZoneProviderPackageName == null ? PROVIDER_MODE_DISABLED : PROVIDER_MODE_ENABLED; + // Changing this state can affect the content of ConfigurationInternal, so listeners need to + // be informed. + mContext.getMainThreadHandler().post(this::handleConfigurationInternalChangeOnMainThread); } @Override @@ -573,6 +581,10 @@ public final class ServiceConfigAccessorImpl implements ServiceConfigAccessor { mTestSecondaryLocationTimeZoneProviderPackageName = null; mTestSecondaryLocationTimeZoneProviderMode = null; mRecordStateChangesForTests = false; + + // Changing LTZP config can affect the content of ConfigurationInternal, so listeners + // need to be informed. + mContext.getMainThreadHandler().post(this::handleConfigurationInternalChangeOnMainThread); } private boolean isTelephonyFallbackSupported() { diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java index f75608e14539..898d02e212f4 100644 --- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java +++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java @@ -336,13 +336,13 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub boolean isTelephonyTimeZoneDetectionSupported() { enforceManageTimeZoneDetectorPermission(); - return mServiceConfigAccessor.isTelephonyTimeZoneDetectionFeatureSupported(); + return mTimeZoneDetectorStrategy.isTelephonyTimeZoneDetectionSupported(); } boolean isGeoTimeZoneDetectionSupported() { enforceManageTimeZoneDetectorPermission(); - return mServiceConfigAccessor.isGeoTimeZoneDetectionFeatureSupported(); + return mTimeZoneDetectorStrategy.isGeoTimeZoneDetectionSupported(); } /** diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java index 6b04adf7de61..95ebd6803cd0 100644 --- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java +++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java @@ -124,4 +124,10 @@ public interface TimeZoneDetectorStrategy extends Dumpable { /** Generates a state snapshot for metrics. */ @NonNull MetricsTimeZoneDetectorState generateMetricsState(); + + /** Returns {@code true} if the device supports telephony time zone detection. */ + boolean isTelephonyTimeZoneDetectionSupported(); + + /** Returns {@code true} if the device supports geolocation time zone detection. */ + boolean isGeoTimeZoneDetectionSupported(); } diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java index e21d0e45ef0e..66c23f5d01a4 100644 --- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java +++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java @@ -396,6 +396,20 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat getLatestGeolocationSuggestion()); } + @Override + public boolean isTelephonyTimeZoneDetectionSupported() { + synchronized (this) { + return mCurrentConfigurationInternal.isTelephonyDetectionSupported(); + } + } + + @Override + public boolean isGeoTimeZoneDetectionSupported() { + synchronized (this) { + return mCurrentConfigurationInternal.isGeoDetectionSupported(); + } + } + private static int scoreTelephonySuggestion(@NonNull TelephonyTimeZoneSuggestion suggestion) { int score; if (suggestion.getZoneId() == null) { diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java index f29c40f74353..37f04501bf28 100644 --- a/services/core/java/com/android/server/vcn/Vcn.java +++ b/services/core/java/com/android/server/vcn/Vcn.java @@ -341,6 +341,9 @@ public class Vcn extends Handler { if (gatewayConnection == null) { logWtf("Found gatewayConnectionConfig without GatewayConnection"); } else { + logInfo( + "Config updated, restarting gateway " + + gatewayConnection.getLogPrefix()); gatewayConnection.teardownAsynchronously(); } } @@ -397,7 +400,7 @@ public class Vcn extends Handler { // If preexisting VcnGatewayConnection(s) satisfy request, return for (VcnGatewayConnectionConfig gatewayConnectionConfig : mVcnGatewayConnections.keySet()) { if (isRequestSatisfiedByGatewayConnectionConfig(request, gatewayConnectionConfig)) { - logDbg("Request already satisfied by existing VcnGatewayConnection: " + request); + logVdbg("Request already satisfied by existing VcnGatewayConnection: " + request); return; } } @@ -407,8 +410,6 @@ public class Vcn extends Handler { for (VcnGatewayConnectionConfig gatewayConnectionConfig : mConfig.getGatewayConnectionConfigs()) { if (isRequestSatisfiedByGatewayConnectionConfig(request, gatewayConnectionConfig)) { - logDbg("Bringing up new VcnGatewayConnection for request " + request); - if (getExposedCapabilitiesForMobileDataState(gatewayConnectionConfig).isEmpty()) { // Skip; this network does not provide any services if mobile data is disabled. continue; @@ -424,6 +425,7 @@ public class Vcn extends Handler { return; } + logInfo("Bringing up new VcnGatewayConnection for request " + request); final VcnGatewayConnection vcnGatewayConnection = mDeps.newVcnGatewayConnection( mVcnContext, @@ -455,7 +457,7 @@ public class Vcn extends Handler { } private void handleGatewayConnectionQuit(VcnGatewayConnectionConfig config) { - logDbg("VcnGatewayConnection quit: " + config); + logInfo("VcnGatewayConnection quit: " + config); mVcnGatewayConnections.remove(config); // Trigger a re-evaluation of all NetworkRequests (to make sure any that can be satisfied @@ -534,7 +536,7 @@ public class Vcn extends Handler { // Trigger re-evaluation of all requests; mobile data state impacts supported caps. mVcnContext.getVcnNetworkProvider().resendAllRequests(mRequestListener); - logDbg("Mobile data " + (mIsMobileDataEnabled ? "enabled" : "disabled")); + logInfo("Mobile data " + (mIsMobileDataEnabled ? "enabled" : "disabled")); } } @@ -569,11 +571,11 @@ public class Vcn extends Handler { } private String getLogPrefix() { - return "[" + return "(" + LogUtils.getHashedSubscriptionGroup(mSubscriptionGroup) + "-" + System.identityHashCode(this) - + "] "; + + ") "; } private void logVdbg(String msg) { diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java index be38005abb63..cefd8efe9658 100644 --- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java +++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java @@ -732,14 +732,11 @@ public class VcnGatewayConnection extends StateMachine { logDbg("Triggering async teardown"); sendDisconnectRequestedAndAcquireWakelock( DISCONNECT_REASON_TEARDOWN, true /* shouldQuit */); - - // TODO: Notify VcnInstance (via callbacks) of permanent teardown of this tunnel, since this - // is also called asynchronously when a NetworkAgent becomes unwanted } @Override protected void onQuitting() { - logDbg("Quitting VcnGatewayConnection"); + logInfo("Quitting VcnGatewayConnection"); if (mNetworkAgent != null) { logWtf("NetworkAgent was non-null in onQuitting"); @@ -794,7 +791,7 @@ public class VcnGatewayConnection extends StateMachine { // TODO(b/180132994): explore safely removing this Thread check mVcnContext.ensureRunningOnLooperThread(); - logDbg( + logInfo( "Selected underlying network changed: " + (underlying == null ? null : underlying.network)); @@ -1335,7 +1332,7 @@ public class VcnGatewayConnection extends StateMachine { protected void handleDisconnectRequested(EventDisconnectRequestedInfo info) { // TODO(b/180526152): notify VcnStatusCallback for Network loss - logDbg("Tearing down. Cause: " + info.reason); + logInfo("Tearing down. Cause: " + info.reason + "; quitting = " + info.shouldQuit); if (info.shouldQuit) { mIsQuitting.setTrue(); } @@ -1353,7 +1350,7 @@ public class VcnGatewayConnection extends StateMachine { protected void handleSafeModeTimeoutExceeded() { mSafeModeTimeoutAlarm = null; - logDbg("Entering safe mode after timeout exceeded"); + logInfo("Entering safe mode after timeout exceeded"); // Connectivity for this GatewayConnection is broken; tear down the Network. teardownNetwork(); @@ -1362,7 +1359,7 @@ public class VcnGatewayConnection extends StateMachine { } protected void logUnexpectedEvent(int what) { - logDbg( + logVdbg( "Unexpected event code " + what + " in state " @@ -1672,7 +1669,7 @@ public class VcnGatewayConnection extends StateMachine { return; } - logDbg("NetworkAgent was unwanted"); + logInfo("NetworkAgent was unwanted"); teardownAsynchronously(); } /* networkUnwantedCallback */, (status) -> { @@ -1748,7 +1745,7 @@ public class VcnGatewayConnection extends StateMachine { tunnelIface, IpSecManager.DIRECTION_FWD, transform); } } catch (IOException e) { - logDbg("Transform application failed for network " + token, e); + logInfo("Transform application failed for network " + token, e); sessionLost(token, e); } } @@ -1782,7 +1779,7 @@ public class VcnGatewayConnection extends StateMachine { tunnelIface.removeAddress(address.getAddress(), address.getPrefixLength()); } } catch (IOException e) { - logDbg("Adding address to tunnel failed for token " + token, e); + logInfo("Adding address to tunnel failed for token " + token, e); sessionLost(token, e); } } @@ -1862,7 +1859,7 @@ public class VcnGatewayConnection extends StateMachine { } private void handleMigrationCompleted(EventMigrationCompletedInfo migrationCompletedInfo) { - logDbg("Migration completed: " + mUnderlying.network); + logInfo("Migration completed: " + mUnderlying.network); applyTransform( mCurrentToken, @@ -1890,7 +1887,7 @@ public class VcnGatewayConnection extends StateMachine { mUnderlying = ((EventUnderlyingNetworkChangedInfo) msg.obj).newUnderlying; if (mUnderlying == null) { - logDbg("Underlying network lost"); + logInfo("Underlying network lost"); // Ignored for now; a new network may be coming up. If none does, the delayed // NETWORK_LOST disconnect will be fired, and tear down the session + network. @@ -1900,7 +1897,7 @@ public class VcnGatewayConnection extends StateMachine { // mUnderlying assumed non-null, given check above. // If network changed, migrate. Otherwise, update any existing networkAgent. if (oldUnderlying == null || !oldUnderlying.network.equals(mUnderlying.network)) { - logDbg("Migrating to new network: " + mUnderlying.network); + logInfo("Migrating to new network: " + mUnderlying.network); mIkeSession.setNetwork(mUnderlying.network); } else { // oldUnderlying is non-null & underlying network itself has not changed @@ -2168,13 +2165,13 @@ public class VcnGatewayConnection extends StateMachine { @Override public void onClosedExceptionally(@NonNull IkeException exception) { - logDbg("IkeClosedExceptionally for token " + mToken, exception); + logInfo("IkeClosedExceptionally for token " + mToken, exception); sessionClosed(mToken, exception); } @Override public void onError(@NonNull IkeProtocolException exception) { - logDbg("IkeError for token " + mToken, exception); + logInfo("IkeError for token " + mToken, exception); // Non-fatal, log and continue. } } @@ -2208,7 +2205,7 @@ public class VcnGatewayConnection extends StateMachine { @Override public void onClosedExceptionally(@NonNull IkeException exception) { - logDbg("ChildClosedExceptionally for token " + mToken, exception); + logInfo("ChildClosedExceptionally for token " + mToken, exception); sessionLost(mToken, exception); } @@ -2234,14 +2231,19 @@ public class VcnGatewayConnection extends StateMachine { } } - private String getLogPrefix() { - return "[" + // Used in Vcn.java, but must be public for mockito to mock this. + public String getLogPrefix() { + return "(" + LogUtils.getHashedSubscriptionGroup(mSubscriptionGroup) + "-" + mConnectionConfig.getGatewayConnectionName() + "-" + System.identityHashCode(this) - + "] "; + + ") "; + } + + private String getTagLogPrefix() { + return "[ " + TAG + " " + getLogPrefix() + "]"; } private void logVdbg(String msg) { @@ -2258,34 +2260,44 @@ public class VcnGatewayConnection extends StateMachine { Slog.d(TAG, getLogPrefix() + msg, tr); } + private void logInfo(String msg) { + Slog.i(TAG, getLogPrefix() + msg); + LOCAL_LOG.log("[INFO] " + getTagLogPrefix() + msg); + } + + private void logInfo(String msg, Throwable tr) { + Slog.i(TAG, getLogPrefix() + msg, tr); + LOCAL_LOG.log("[INFO] " + getTagLogPrefix() + msg + tr); + } + private void logWarn(String msg) { Slog.w(TAG, getLogPrefix() + msg); - LOCAL_LOG.log(getLogPrefix() + "WARN: " + msg); + LOCAL_LOG.log("[WARN] " + getTagLogPrefix() + msg); } private void logWarn(String msg, Throwable tr) { Slog.w(TAG, getLogPrefix() + msg, tr); - LOCAL_LOG.log(getLogPrefix() + "WARN: " + msg + tr); + LOCAL_LOG.log("[WARN] " + getTagLogPrefix() + msg + tr); } private void logErr(String msg) { Slog.e(TAG, getLogPrefix() + msg); - LOCAL_LOG.log(getLogPrefix() + "ERR: " + msg); + LOCAL_LOG.log("[ERR ] " + getTagLogPrefix() + msg); } private void logErr(String msg, Throwable tr) { Slog.e(TAG, getLogPrefix() + msg, tr); - LOCAL_LOG.log(getLogPrefix() + "ERR: " + msg + tr); + LOCAL_LOG.log("[ERR ] " + getTagLogPrefix() + msg + tr); } private void logWtf(String msg) { Slog.wtf(TAG, getLogPrefix() + msg); - LOCAL_LOG.log(getLogPrefix() + "WTF: " + msg); + LOCAL_LOG.log("[WTF ] " + msg); } private void logWtf(String msg, Throwable tr) { Slog.wtf(TAG, getLogPrefix() + msg, tr); - LOCAL_LOG.log(getLogPrefix() + "WTF: " + msg + tr); + LOCAL_LOG.log("[WTF ] " + msg + tr); } /** diff --git a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java index ca2e449ffc25..a3babf7c9fff 100644 --- a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java +++ b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java @@ -48,6 +48,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; import com.android.server.vcn.VcnContext; +import com.android.server.vcn.util.LogUtils; import java.util.ArrayList; import java.util.Collections; @@ -368,6 +369,18 @@ public class UnderlyingNetworkController { return; } + String allNetworkPriorities = ""; + for (UnderlyingNetworkRecord record : sorted) { + if (!allNetworkPriorities.isEmpty()) { + allNetworkPriorities += ", "; + } + allNetworkPriorities += record.network + ": " + record.getPriorityClass(); + } + logInfo( + "Selected network changed to " + + (candidate == null ? null : candidate.network) + + ", selected from list: " + + allNetworkPriorities); mCurrentRecord = candidate; mCb.onSelectedUnderlyingNetworkChanged(mCurrentRecord); } @@ -478,14 +491,38 @@ public class UnderlyingNetworkController { } } - private static void logWtf(String msg) { + private String getLogPrefix() { + return "(" + + LogUtils.getHashedSubscriptionGroup(mSubscriptionGroup) + + "-" + + mConnectionConfig.getGatewayConnectionName() + + "-" + + System.identityHashCode(this) + + ") "; + } + + private String getTagLogPrefix() { + return "[ " + TAG + " " + getLogPrefix() + "]"; + } + + private void logInfo(String msg) { + Slog.i(TAG, getLogPrefix() + msg); + LOCAL_LOG.log("[INFO] " + getTagLogPrefix() + msg); + } + + private void logInfo(String msg, Throwable tr) { + Slog.i(TAG, getLogPrefix() + msg, tr); + LOCAL_LOG.log("[INFO] " + getTagLogPrefix() + msg + tr); + } + + private void logWtf(String msg) { Slog.wtf(TAG, msg); - LOCAL_LOG.log(TAG + " WTF: " + msg); + LOCAL_LOG.log(TAG + "[WTF ] " + getTagLogPrefix() + msg); } - private static void logWtf(String msg, Throwable tr) { + private void logWtf(String msg, Throwable tr) { Slog.wtf(TAG, msg, tr); - LOCAL_LOG.log(TAG + " WTF: " + msg + tr); + LOCAL_LOG.log(TAG + "[WTF ] " + getTagLogPrefix() + msg + tr); } /** Dumps the state of this record for logging and debugging purposes. */ diff --git a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java index c0488b18cb65..06f92805ad2b 100644 --- a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java +++ b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java @@ -41,11 +41,15 @@ import java.util.Objects; * @hide */ public class UnderlyingNetworkRecord { + private static final int PRIORITY_CLASS_INVALID = Integer.MAX_VALUE; + @NonNull public final Network network; @NonNull public final NetworkCapabilities networkCapabilities; @NonNull public final LinkProperties linkProperties; public final boolean isBlocked; + private int mPriorityClass = PRIORITY_CLASS_INVALID; + @VisibleForTesting(visibility = Visibility.PRIVATE) public UnderlyingNetworkRecord( @NonNull Network network, @@ -58,6 +62,34 @@ public class UnderlyingNetworkRecord { this.isBlocked = isBlocked; } + private int getOrCalculatePriorityClass( + VcnContext vcnContext, + List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates, + ParcelUuid subscriptionGroup, + TelephonySubscriptionSnapshot snapshot, + UnderlyingNetworkRecord currentlySelected, + PersistableBundle carrierConfig) { + // Never changes after the underlying network record is created. + if (mPriorityClass == PRIORITY_CLASS_INVALID) { + mPriorityClass = + NetworkPriorityClassifier.calculatePriorityClass( + vcnContext, + this, + underlyingNetworkTemplates, + subscriptionGroup, + snapshot, + currentlySelected, + carrierConfig); + } + + return mPriorityClass; + } + + // Used in UnderlyingNetworkController + int getPriorityClass() { + return mPriorityClass; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -84,18 +116,16 @@ public class UnderlyingNetworkRecord { PersistableBundle carrierConfig) { return (left, right) -> { final int leftIndex = - NetworkPriorityClassifier.calculatePriorityClass( + left.getOrCalculatePriorityClass( vcnContext, - left, underlyingNetworkTemplates, subscriptionGroup, snapshot, currentlySelected, carrierConfig); final int rightIndex = - NetworkPriorityClassifier.calculatePriorityClass( + right.getOrCalculatePriorityClass( vcnContext, - right, underlyingNetworkTemplates, subscriptionGroup, snapshot, @@ -142,16 +172,15 @@ public class UnderlyingNetworkRecord { pw.increaseIndent(); final int priorityIndex = - NetworkPriorityClassifier.calculatePriorityClass( + getOrCalculatePriorityClass( vcnContext, - this, underlyingNetworkTemplates, subscriptionGroup, snapshot, currentlySelected, carrierConfig); - pw.println("Priority index:" + priorityIndex); + pw.println("Priority index: " + priorityIndex); pw.println("mNetwork: " + network); pw.println("mNetworkCapabilities: " + networkCapabilities); pw.println("mLinkProperties: " + linkProperties); diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java index 18e9904142eb..ac635a0746c5 100644 --- a/services/core/java/com/android/server/vibrator/VibrationSettings.java +++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java @@ -238,8 +238,6 @@ final class VibrationSettings { // Listen to all settings that might affect the result of Vibrator.getVibrationIntensity. registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES)); registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_ON)); - registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_WHEN_RINGING)); - registerSettingsObserver(Settings.System.getUriFor(Settings.System.APPLY_RAMPING_RINGER)); registerSettingsObserver(Settings.System.getUriFor( Settings.System.HAPTIC_FEEDBACK_ENABLED)); registerSettingsObserver( @@ -449,19 +447,12 @@ final class VibrationSettings { mCurrentVibrationIntensities.put(USAGE_NOTIFICATION, notificationIntensity); mCurrentVibrationIntensities.put(USAGE_MEDIA, mediaIntensity); mCurrentVibrationIntensities.put(USAGE_UNKNOWN, mediaIntensity); + mCurrentVibrationIntensities.put(USAGE_RINGTONE, ringIntensity); // Communication request is not disabled by the notification setting. mCurrentVibrationIntensities.put(USAGE_COMMUNICATION_REQUEST, positiveNotificationIntensity); - if (!loadBooleanSetting(Settings.System.VIBRATE_WHEN_RINGING) - && !loadBooleanSetting(Settings.System.APPLY_RAMPING_RINGER)) { - // Make sure deprecated boolean setting still disables ringtone vibrations. - mCurrentVibrationIntensities.put(USAGE_RINGTONE, Vibrator.VIBRATION_INTENSITY_OFF); - } else { - mCurrentVibrationIntensities.put(USAGE_RINGTONE, ringIntensity); - } - // This should adapt the behavior preceding the introduction of this new setting // key, which is to apply HAPTIC_FEEDBACK_INTENSITY, unless it's disabled. mCurrentVibrationIntensities.put(USAGE_HARDWARE_FEEDBACK, hardwareFeedbackIntensity); diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index c52a4e499f1f..63619e543a6d 100644 --- a/services/core/java/com/android/server/wm/AccessibilityController.java +++ b/services/core/java/com/android/server/wm/AccessibilityController.java @@ -446,20 +446,6 @@ final class AccessibilityController { // Not relevant for the window observer. } - MagnificationSpec getMagnificationSpecForWindow(WindowState windowState) { - if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) { - mAccessibilityTracing.logTrace(TAG + ".getMagnificationSpecForWindow", - FLAGS_MAGNIFICATION_CALLBACK, - "windowState={" + windowState + "}"); - } - final int displayId = windowState.getDisplayId(); - final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId); - if (displayMagnifier != null) { - return displayMagnifier.getMagnificationSpecForWindow(windowState); - } - return null; - } - boolean hasCallbacks() { if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK | FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK)) { diff --git a/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java b/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java index ca636b3552e9..6e5011dacd82 100644 --- a/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java +++ b/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java @@ -596,8 +596,6 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener { * surface flinger to the accessibility framework. */ public static class AccessibilityWindow { - private static final Region TEMP_REGION = new Region(); - private static final RectF TEMP_RECTF = new RectF(); // Data private IWindow mWindow; private int mDisplayId; @@ -615,15 +613,16 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener { private final Region mLetterBoxBounds = new Region(); private WindowInfo mWindowInfo; + /** * Returns the instance after initializing the internal data. * @param service The window manager service. * @param inputWindowHandle The window from the surface flinger. - * @param inverseMatrix The magnification spec inverse matrix. + * @param magnificationInverseMatrix The magnification spec inverse matrix. */ public static AccessibilityWindow initializeData(WindowManagerService service, - InputWindowHandle inputWindowHandle, Matrix inverseMatrix, IBinder pipIBinder, - Matrix displayMatrix) { + InputWindowHandle inputWindowHandle, Matrix magnificationInverseMatrix, + IBinder pipIBinder, Matrix displayMatrix) { final IWindow window = inputWindowHandle.getWindow(); final WindowState windowState = window != null ? service.mWindowMap.get( window.asBinder()) : null; @@ -655,13 +654,35 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener { inputWindowHandle.frameTop, inputWindowHandle.frameRight, inputWindowHandle.frameBottom); getTouchableRegionInWindow(instance.mShouldMagnify, inputWindowHandle.touchableRegion, - instance.mTouchableRegionInWindow, windowFrame, inverseMatrix, displayMatrix); + instance.mTouchableRegionInWindow, windowFrame, magnificationInverseMatrix, + displayMatrix); getUnMagnifiedTouchableRegion(instance.mShouldMagnify, inputWindowHandle.touchableRegion, instance.mTouchableRegionInScreen, - inverseMatrix, displayMatrix); + magnificationInverseMatrix, displayMatrix); instance.mWindowInfo = windowState != null ? windowState.getWindowInfo() : getWindowInfoForWindowlessWindows(instance); + // Compute the transform matrix that will transform bounds from the window + // coordinates to screen coordinates. + final Matrix inverseTransform = new Matrix(); + inputWindowHandle.transform.invert(inverseTransform); + inverseTransform.postConcat(displayMatrix); + inverseTransform.getValues(instance.mWindowInfo.mTransformMatrix); + + // Compute the magnification spec matrix. + final Matrix magnificationSpecMatrix = new Matrix(); + if (instance.shouldMagnify() && magnificationInverseMatrix != null + && !magnificationInverseMatrix.isIdentity()) { + if (magnificationInverseMatrix.invert(magnificationSpecMatrix)) { + magnificationSpecMatrix.getValues(sTempFloats); + final MagnificationSpec spec = instance.mWindowInfo.mMagnificationSpec; + spec.scale = sTempFloats[Matrix.MSCALE_X]; + spec.offsetX = sTempFloats[Matrix.MTRANS_X]; + spec.offsetY = sTempFloats[Matrix.MTRANS_Y]; + } else { + Slog.w(TAG, "can't find spec"); + } + } return instance; } @@ -779,7 +800,7 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener { // for the consistency and match developers expectation. // So we need to make the intersection between the frame and touchable region to // obtain the real touch region in the screen. - Region touchRegion = TEMP_REGION; + Region touchRegion = new Region(); touchRegion.set(inRegion); touchRegion.op(frame, Region.Op.INTERSECT); @@ -807,8 +828,7 @@ public final class AccessibilityWindowsPopulator extends WindowInfosListener { forEachRect(inRegion, rect -> { // Move to origin as all transforms are captured by the matrix. - RectF windowFrame = TEMP_RECTF; - windowFrame.set(rect); + RectF windowFrame = new RectF(rect); displayMatrix.mapRect(windowFrame); inverseMatrix.mapRect(windowFrame); diff --git a/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java b/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java index d2053fa25ad8..400460a1e656 100644 --- a/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java +++ b/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java @@ -29,7 +29,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** - * Callback to intercept activity starts and possibly block/redirect them. + * Callback to intercept activity starts and possibly block/redirect them. The callback methods will + * be called with the WindowManagerGlobalLock held. */ public abstract class ActivityInterceptorCallback { /** diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 0ebc9e80455e..1956cee11f90 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -3974,6 +3974,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } else { onRemovedFromDisplay(); } + mActivityRecordInputSink.releaseSurfaceControl(); + super.removeImmediately(); } @@ -5558,7 +5560,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * this activity when embedded in untrusted mode. */ boolean hasOverlayOverUntrustedModeEmbedded() { - if (!isEmbeddedInUntrustedMode() || getRootTask() == null) { + if (!isEmbeddedInUntrustedMode() || getTask() == null) { // The activity is not embedded in untrusted mode. return false; } @@ -5566,7 +5568,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // Check if there are any activities with different UID over the activity that is embedded // in untrusted mode. Traverse bottom to top with boundary so that it will only check // activities above this activity. - final ActivityRecord differentUidOverlayActivity = getRootTask().getActivity( + final ActivityRecord differentUidOverlayActivity = getTask().getActivity( a -> a.getUid() != getUid(), this /* boundary */, false /* includeBoundary */, false /* traverseTopToBottom */); return differentUidOverlayActivity != null; @@ -6305,7 +6307,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // starting window is drawn, the transition can start earlier. Exclude finishing and bubble // because it may be a trampoline. if (!wasTaskVisible && mStartingData != null && !finishing && !mLaunchedFromBubble - && !mDisplayContent.mAppTransition.isReady() + && mVisibleRequested && !mDisplayContent.mAppTransition.isReady() && !mDisplayContent.mAppTransition.isRunning() && mDisplayContent.isNextTransitionForward()) { // The pending transition state will be cleared after the transition is started, so diff --git a/services/core/java/com/android/server/wm/ActivityRecordInputSink.java b/services/core/java/com/android/server/wm/ActivityRecordInputSink.java index ce49a8675890..23a832496cc9 100644 --- a/services/core/java/com/android/server/wm/ActivityRecordInputSink.java +++ b/services/core/java/com/android/server/wm/ActivityRecordInputSink.java @@ -99,4 +99,11 @@ class ActivityRecordInputSink { return inputWindowHandle; } + void releaseSurfaceControl() { + if (mSurfaceControl != null) { + mSurfaceControl.release(); + mSurfaceControl = null; + } + } + } diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index eb912d4c2747..75d462131aae 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -2481,6 +2481,12 @@ class ActivityStarter { if (inTaskFragment == null) { inTaskFragment = TaskFragment.fromTaskFragmentToken( mOptions.getLaunchTaskFragmentToken(), mService); + if (inTaskFragment != null && inTaskFragment.isEmbeddedTaskFragmentInPip()) { + // Do not start activity in TaskFragment in a PIP Task. + Slog.w(TAG, "Can not start activity in TaskFragment in PIP: " + + inTaskFragment); + inTaskFragment = null; + } } } @@ -2638,14 +2644,16 @@ class ActivityStarter { Slog.w(TAG, "startActivity called from finishing " + mSourceRecord + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent); mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK; - mNewTaskInfo = mSourceRecord.info; - // It is not guaranteed that the source record will have a task associated with it. For, - // example, if this method is being called for processing a pending activity launch, it - // is possible that the activity has been removed from the task after the launch was - // enqueued. + // It is not guaranteed that the source record will have a task associated with it. + // For example, if this method is being called for processing a pending activity + // launch, it is possible that the activity has been removed from the task after the + // launch was enqueued. final Task sourceTask = mSourceRecord.getTask(); - mNewTaskIntent = sourceTask != null ? sourceTask.intent : null; + if (sourceTask == null || sourceTask.getTopNonFinishingActivity() == null) { + mNewTaskInfo = mSourceRecord.info; + mNewTaskIntent = sourceTask != null ? sourceTask.intent : null; + } } mSourceRecord = null; mSourceRootTask = null; diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java index 9bf69bcc2eaa..a4b216fc7ff8 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java @@ -512,9 +512,6 @@ public abstract class ActivityTaskManagerInternal { public abstract void onUidInactive(int uid); public abstract void onUidProcStateChanged(int uid, int procState); - public abstract void onUidAddedToPendingTempAllowlist(int uid, String tag); - public abstract void onUidRemovedFromPendingTempAllowlist(int uid); - /** Handle app crash event in {@link android.app.IActivityController} if there is one. */ public abstract boolean handleAppCrashInActivityController(String processName, int pid, String shortMsg, String longMsg, long timeMillis, String stackTrace, diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 1f7c0efa572e..d99770717a5d 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -62,7 +62,6 @@ import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIV import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RTL; import static android.provider.Settings.Global.HIDE_ERROR_DIALOGS; import static android.provider.Settings.System.FONT_SCALE; -import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static android.view.WindowManager.TRANSIT_WAKE; @@ -284,7 +283,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; @@ -382,7 +380,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { private AppOpsManager mAppOpsManager; /** All active uids in the system. */ final MirrorActiveUids mActiveUids = new MirrorActiveUids(); - private final SparseArray<String> mPendingTempAllowlist = new SparseArray<>(); /** All processes currently running that might have a window organized by name. */ final ProcessMap<WindowProcessController> mProcessNames = new ProcessMap<>(); /** All processes we currently have running mapped by pid and uid */ @@ -6439,20 +6436,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public void onUidAddedToPendingTempAllowlist(int uid, String tag) { - synchronized (mGlobalLockWithoutBoost) { - mPendingTempAllowlist.put(uid, tag); - } - } - - @Override - public void onUidRemovedFromPendingTempAllowlist(int uid) { - synchronized (mGlobalLockWithoutBoost) { - mPendingTempAllowlist.remove(uid); - } - } - - @Override public boolean handleAppCrashInActivityController(String processName, int pid, String shortMsg, String longMsg, long timeMillis, String stackTrace, Runnable killCrashingAppCallback) { diff --git a/services/core/java/com/android/server/wm/BLASTSync.md b/services/core/java/com/android/server/wm/BLASTSync.md index 2f39d6db385e..dbb28d4d5ae3 100644 --- a/services/core/java/com/android/server/wm/BLASTSync.md +++ b/services/core/java/com/android/server/wm/BLASTSync.md @@ -106,3 +106,88 @@ to the client via ClientTransaction), we haven't even incremented the seqId yet, at the same time as the state? We solve this by pushing all client communication through a handler thread that has to acquire the lock. This ensures we uphold requirement 2. += Transaction ordering = + +Applying transactions from different process, and in to different server side transaction queues +raises various questions about transaction ordering. There are two tricky questions in this +domain that we address here: + 1. The ordering of Transactions from a single BLASTBufferQueue wrt to eachother + 2. The ordering of non synced WM updates to syncable state, wrt a BLASTSyncEngine + transaction + +== Ordering of Transactions in a single BBQ == + +We can see if sync is never involved, there are never any real questions about ordering. +Even using one-way setTransactionState, the calls are from a single thread to a single +interface on another, and will be ordered. When we hand out transactions for sync +is where issues can start to arise. Obviously if we apply another transaction +immediately after handing out the sync transaction it could arrive first, and this would +cause an ordering issue. It's also possible that the sync transaction arrives before the +transaction applied before it (since setTransactionState is one way from BBQ). Even if +the transactions are applied in the right order, it's possible for them to be +commited out of sync, as the BBQ and SyncConsumer may be using different apply tokens +resulting in the transaction being placed in different server side queues. + +To solve these issues, we use a scheme involving "barrier transactions". We show how +this scheme handles every permutation of (Sync, NotSync). + +1. NotSync, NotSync: This is the trivial case. As long as both buffers are submitted from + the same thread, they will arrive in SF in order, and SF will place them in the same + queue (since there is a shared apply token), which it will process in order. +2. Sync, NotSync: For sync transactions we register a commit callback, and require it to + be fired before applying the next transaction. Since the commit callback is only + fired when the transaction has latched on the server side, any transaction applied + later, must occur later. +3. Sync, Sync: Ordering of consecutive sync transactions is delegated to the sync + consumer +4. NotSync, Sync: This is the trickiest case, as we don't want to set a commit callback + on not sync transactions (as this would incur an unacceptable performance overhead). + Further complicating matters, we want to apply them with one-way binder, since + this is the hot path for all graphical updates. To solve this we use a + "setBufferHasBarrier" system. Sync transactions (before they are handed out) + are tagged with a barrier, referring to the frame number of the last + non sync transaction. SurfaceFlinger will ensure the correct ordering + by stalling transactions in the queue until barriers are fulfilled. This barrier + primitive is dangerous, because it could result in deadlocking, but its ok in + this scenario since only BBQ uses its apply token. + +We can see from this that all frames are in order. + +== Ordering of WM updates to syncable state == + +A second interesting question, is about the ordering of WM updates to syncable-state. In +the WM we frequently write code like + getPendingTransaction/getSyncTransaction().show(mSurfaceControl). +In normal operation, getSyncTransaction and getPendingTransaction both refer to the same +transaction which is the displaycontent pendingtransaction, applied by the WindowManager. +During sync, each syncing container will instead use its mSyncTransaction, which will +eventually be merged to be applied by the WindowManager. We can see that we have a congruent +"problem" to BLASTBufferQueue transaction ordering. Namely, earlier state updates which were +given to SysUI could end up being applied later than state updates which were made later but +directly applied by the WM. We can break this down in to two cases: +=== getPendingTransaction() and getSyncTransaction() ordering === +It's possible for code like this to occur: +getSyncTransaction().OP1 +getPendingTransaction().OP2 +applyPendingTransaction +applySyncTransaction + +in this case the change in OP2 was made later, but occurs first. We define this case as +intended behavior, and say there is no ordering guarantee between the pending +and sync transactions. This means the pending transaction is only useful in +some marginal cases and should probably be considered a deprecated primitive. +=== getSyncTransaction() and getSyncTransaction() ordering === +However, we take great care to ensure usage of getSyncTransaction() reflects +the ordering the developer would expect. BLASTSyncEngine will register +a commit callback on all transactions it hands out. In the interval between +receiving this commit callback and sending out the transaction, we may have other +data enter getSyncTransaction. If we returned the pending transaction +(as we do in normal time), then we could create ordering issues, since the pending +transactions ordering is undefined. Instead we continue to return the sync transaction +during this interval. If no second sync has started by the time we receive +the commit callback, then we directly apply this left over data in the sync transaction +guaranteed it will be ordered correctly, and return to using the pending +transaction. If a second sync has started, then we just allow the data +to persist in the mSyncTransaction, potentially to be overwritten +by the new sync. It will eventually apply with SysUI's apply token and +ordering will be maintained. diff --git a/services/core/java/com/android/server/wm/BLASTSyncEngine.java b/services/core/java/com/android/server/wm/BLASTSyncEngine.java index 6e205be5b574..3f300bce54c4 100644 --- a/services/core/java/com/android/server/wm/BLASTSyncEngine.java +++ b/services/core/java/com/android/server/wm/BLASTSyncEngine.java @@ -19,6 +19,7 @@ package com.android.server.wm; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SYNC_ENGINE; +import static com.android.server.wm.WindowManagerService.H.WINDOW_STATE_BLAST_SYNC_TIMEOUT; import android.annotation.NonNull; import android.os.Trace; @@ -147,6 +148,33 @@ class BLASTSyncEngine { for (WindowContainer wc : mRootMembers) { wc.finishSync(merged, false /* cancel */); } + + final ArraySet<WindowContainer> wcAwaitingCommit = new ArraySet<>(); + for (WindowContainer wc : mRootMembers) { + wc.waitForSyncTransactionCommit(wcAwaitingCommit); + } + final Runnable callback = new Runnable() { + // Can run a second time if the action completes after the timeout. + boolean ran = false; + public void run() { + synchronized (mWm.mGlobalLock) { + if (ran) { + return; + } + mWm.mH.removeCallbacks(this); + ran = true; + SurfaceControl.Transaction t = new SurfaceControl.Transaction(); + for (WindowContainer wc : wcAwaitingCommit) { + wc.onSyncTransactionCommitted(t); + } + t.apply(); + wcAwaitingCommit.clear(); + } + } + }; + merged.addTransactionCommittedListener((r) -> { r.run(); }, callback::run); + mWm.mH.postDelayed(callback, WINDOW_STATE_BLAST_SYNC_TIMEOUT); + Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "onTransactionReady"); mListener.onTransactionReady(mSyncId, merged); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java index f70dc52bf5e7..0ed671804fe4 100644 --- a/services/core/java/com/android/server/wm/BackNavigationController.java +++ b/services/core/java/com/android/server/wm/BackNavigationController.java @@ -94,12 +94,22 @@ class BackNavigationController { } int backType = BackNavigationInfo.TYPE_UNDEFINED; + + // The currently visible activity (if any). + ActivityRecord currentActivity = null; + + // The currently visible task (if any). + Task currentTask = null; + + // The previous task we're going back to. Can be the same as currentTask, if there are + // multiple Activities in the Stack. Task prevTask = null; - ActivityRecord prev; + + // The previous activity we're going back to. This can be either a child of currentTask + // if there are more than one Activity in currentTask, or a child of prevTask, if + // currentActivity is the last child of currentTask. + ActivityRecord prevActivity; WindowContainer<?> removedWindowContainer = null; - ActivityRecord activityRecord = null; - ActivityRecord prevTaskTopActivity = null; - Task task = null; SurfaceControl animationLeashParent = null; HardwareBuffer screenshotBuffer = null; RemoteAnimationTarget topAppTarget = null; @@ -143,20 +153,37 @@ class BackNavigationController { } if (window == null) { - // We don't have any focused window, fallback ont the top task of the focused + // We don't have any focused window, fallback ont the top currentTask of the focused // display. ProtoLog.w(WM_DEBUG_BACK_PREVIEW, - "No focused window, defaulting to top task's window"); - task = wmService.mAtmService.getTopDisplayFocusedRootTask(); - window = task.getWindow(WindowState::isFocused); + "No focused window, defaulting to top current task's window"); + currentTask = wmService.mAtmService.getTopDisplayFocusedRootTask(); + window = currentTask.getWindow(WindowState::isFocused); } // Now let's find if this window has a callback from the client side. OnBackInvokedCallbackInfo callbackInfo = null; if (window != null) { - activityRecord = window.mActivityRecord; - task = window.getTask(); + currentActivity = window.mActivityRecord; + currentTask = window.getTask(); callbackInfo = window.getOnBackInvokedCallbackInfo(); + final DisplayContent displayContent = window.getDisplayContent(); + + // When IME is shown, return the more prioritized callback between IME and app. + // Priority ordering follows: OVERLAY, IME, DEFAULT. + if (displayContent != null && displayContent.getImeContainer().isVisible()) { + WindowState imeWindow = displayContent.getImeContainer().getWindow( + windowState -> windowState.getOnBackInvokedCallbackInfo() != null); + if (imeWindow != null) { + OnBackInvokedCallbackInfo imeCallbackInfo = + imeWindow.getOnBackInvokedCallbackInfo(); + if (imeCallbackInfo != null && (callbackInfo == null + || callbackInfo.getPriority() <= imeCallbackInfo.getPriority())) { + callbackInfo = imeCallbackInfo; + } + } + } + if (callbackInfo == null) { Slog.e(TAG, "No callback registered, returning null."); return null; @@ -167,9 +194,9 @@ class BackNavigationController { infoBuilder.setOnBackInvokedCallback(callbackInfo.getCallback()); } - ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "startBackNavigation task=%s, " + ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "startBackNavigation currentTask=%s, " + "topRunningActivity=%s, callbackInfo=%s, currentFocus=%s", - task, activityRecord, callbackInfo, window); + currentTask, currentActivity, callbackInfo, window); if (window == null) { Slog.e(TAG, "Window is null, returning null."); @@ -179,21 +206,19 @@ class BackNavigationController { // If we don't need to set up the animation, we return early. This is the case when // - We have an application callback. // - We don't have any ActivityRecord or Task to animate. - // - The IME is opened, and we just need to close it. // - The home activity is the focused activity. if (backType == BackNavigationInfo.TYPE_CALLBACK - || activityRecord == null - || task == null - || task.getDisplayContent().getImeContainer().isVisible() - || activityRecord.isActivityTypeHome()) { + || currentActivity == null + || currentTask == null + || currentActivity.isActivityTypeHome()) { return infoBuilder .setType(backType) .build(); } // We don't have an application callback, let's find the destination of the back gesture - Task finalTask = task; - prev = task.getActivity( + Task finalTask = currentTask; + prevActivity = currentTask.getActivity( (r) -> !r.finishing && r.getTask() == finalTask && !r.isTopRunningActivity()); if (window.getParent().getChildCount() > 1 && window.getParent().getChildAt(0) != window) { @@ -201,24 +226,24 @@ class BackNavigationController { // activity, we won't close the activity. backType = BackNavigationInfo.TYPE_DIALOG_CLOSE; removedWindowContainer = window; - } else if (prev != null) { - // We have another Activity in the same task to go to + } else if (prevActivity != null) { + // We have another Activity in the same currentTask to go to backType = BackNavigationInfo.TYPE_CROSS_ACTIVITY; - removedWindowContainer = activityRecord; - } else if (task.returnsToHomeRootTask()) { + removedWindowContainer = currentActivity; + } else if (currentTask.returnsToHomeRootTask()) { // Our Task should bring back to home - removedWindowContainer = task; + removedWindowContainer = currentTask; backType = BackNavigationInfo.TYPE_RETURN_TO_HOME; - } else if (activityRecord.isRootOfTask()) { + } else if (currentActivity.isRootOfTask()) { // TODO(208789724): Create single source of truth for this, maybe in // RootWindowContainer - // TODO: Also check Task.shouldUpRecreateTaskLocked() for prev logic - prevTask = task.mRootWindowContainer.getTaskBelow(task); - removedWindowContainer = task; + // TODO: Also check Task.shouldUpRecreateTaskLocked() for prevActivity logic + prevTask = currentTask.mRootWindowContainer.getTaskBelow(currentTask); + removedWindowContainer = currentTask; + prevActivity = prevTask.getTopNonFinishingActivity(); if (prevTask.isActivityTypeHome()) { backType = BackNavigationInfo.TYPE_RETURN_TO_HOME; } else { - prev = prevTask.getTopNonFinishingActivity(); backType = BackNavigationInfo.TYPE_CROSS_TASK; } } @@ -229,7 +254,7 @@ class BackNavigationController { ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Previous Destination is Activity:%s Task:%s " + "removedContainer:%s, backType=%s", - prev != null ? prev.mActivityComponent : null, + prevActivity != null ? prevActivity.mActivityComponent : null, prevTask != null ? prevTask.getName() : null, removedWindowContainer, BackNavigationInfo.typeToString(backType)); @@ -241,7 +266,8 @@ class BackNavigationController { && !removedWindowContainer.hasCommittedReparentToAnimationLeash(); if (prepareAnimation) { - taskWindowConfiguration = task.getTaskInfo().configuration.windowConfiguration; + taskWindowConfiguration = + currentTask.getTaskInfo().configuration.windowConfiguration; infoBuilder.setTaskWindowConfiguration(taskWindowConfiguration); // Prepare a leash to animate the current top window @@ -254,32 +280,36 @@ class BackNavigationController { removedWindowContainer.reparentSurfaceControl(tx, animLeash); animationLeashParent = removedWindowContainer.getAnimationLeashParent(); topAppTarget = createRemoteAnimationTargetLocked(removedWindowContainer, - activityRecord, - task, animLeash); + currentActivity, + currentTask, animLeash); infoBuilder.setDepartingAnimationTarget(topAppTarget); } //TODO(207481538) Remove once the infrastructure to support per-activity screenshot is // implemented. For now we simply have the mBackScreenshots hash map that dumbly // saves the screenshots. - if (needsScreenshot(backType) && prev != null && prev.mActivityComponent != null) { - screenshotBuffer = getActivitySnapshot(task, prev.mActivityComponent); + if (needsScreenshot(backType) && prevActivity != null + && prevActivity.mActivityComponent != null) { + screenshotBuffer = + getActivitySnapshot(currentTask, prevActivity.mActivityComponent); } - if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && isAnimationEnabled()) { - task.mBackGestureStarted = true; + // Special handling for back to home animation + if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && isAnimationEnabled() + && prevTask != null) { + currentTask.mBackGestureStarted = true; // Make launcher show from behind by marking its top activity as visible and // launch-behind to bump its visibility for the duration of the back gesture. - prevTaskTopActivity = prevTask.getTopNonFinishingActivity(); - if (prevTaskTopActivity != null) { - if (!prevTaskTopActivity.mVisibleRequested) { - prevTaskTopActivity.setVisibility(true); + prevActivity = prevTask.getTopNonFinishingActivity(); + if (prevActivity != null) { + if (!prevActivity.mVisibleRequested) { + prevActivity.setVisibility(true); } - prevTaskTopActivity.mLaunchTaskBehind = true; + prevActivity.mLaunchTaskBehind = true; ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Setting Activity.mLauncherTaskBehind to true. Activity=%s", - prevTaskTopActivity); - prevTaskTopActivity.mRootWindowContainer.ensureActivitiesVisible( + prevActivity); + prevActivity.mRootWindowContainer.ensureActivitiesVisible( null /* starting */, 0 /* configChanges */, false /* preserveWindows */); } @@ -290,7 +320,7 @@ class BackNavigationController { if (topAppTarget != null && needsScreenshot(backType) && prevTask != null && screenshotBuffer == null) { SurfaceControl.Builder builder = new SurfaceControl.Builder() - .setName("BackPreview Screenshot for " + prev) + .setName("BackPreview Screenshot for " + prevActivity) .setParent(animationLeashParent) .setHidden(false) .setBLASTLayer(); @@ -302,12 +332,12 @@ class BackNavigationController { // The Animation leash needs to be above the screenshot surface, but the animation leash // needs to be added before to be in the synchronized block. tx.setLayer(topAppTarget.leash, 1); - tx.apply(); - + } - WindowContainer<?> finalRemovedWindowContainer = removedWindowContainer; + WindowContainer<?> finalRemovedWindowContainer = removedWindowContainer; + if (finalRemovedWindowContainer != null) { try { - activityRecord.token.linkToDeath( + currentActivity.token.linkToDeath( () -> resetSurfaces(finalRemovedWindowContainer), 0); } catch (RemoteException e) { Slog.e(TAG, "Failed to link to death", e); @@ -315,11 +345,16 @@ class BackNavigationController { return null; } - RemoteCallback onBackNavigationDone = new RemoteCallback( - result -> resetSurfaces(finalRemovedWindowContainer - )); + int finalBackType = backType; + ActivityRecord finalprevActivity = prevActivity; + Task finalTask = currentTask; + RemoteCallback onBackNavigationDone = new RemoteCallback(result -> onBackNavigationDone( + result, finalRemovedWindowContainer, finalBackType, finalTask, + finalprevActivity)); infoBuilder.setOnBackNavigationDone(onBackNavigationDone); } + + tx.apply(); return infoBuilder.build(); } @@ -348,14 +383,13 @@ class BackNavigationController { } private void onBackNavigationDone( - Bundle result, WindowContainer windowContainer, int backType, - Task task, ActivityRecord prevTaskTopActivity) { + Bundle result, WindowContainer<?> windowContainer, int backType, + Task task, ActivityRecord prevActivity) { SurfaceControl surfaceControl = windowContainer.getSurfaceControl(); - boolean triggerBack = result != null - ? result.getBoolean(BackNavigationInfo.KEY_TRIGGER_BACK) - : false; + boolean triggerBack = result != null && result.getBoolean( + BackNavigationInfo.KEY_TRIGGER_BACK); ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "onBackNavigationDone backType=%s, " - + "task=%s, prevTaskTopActivity=%s", backType, task, prevTaskTopActivity); + + "task=%s, prevActivity=%s", backType, task, prevActivity); if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && isAnimationEnabled()) { if (triggerBack) { @@ -367,13 +401,13 @@ class BackNavigationController { t.apply(); } } - if (prevTaskTopActivity != null && !triggerBack) { + if (prevActivity != null && !triggerBack) { // Restore the launch-behind state. - task.mTaskSupervisor.scheduleLaunchTaskBehindComplete(prevTaskTopActivity.token); - prevTaskTopActivity.mLaunchTaskBehind = false; + task.mTaskSupervisor.scheduleLaunchTaskBehindComplete(prevActivity.token); + prevActivity.mLaunchTaskBehind = false; ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Setting Activity.mLauncherTaskBehind to false. Activity=%s", - prevTaskTopActivity); + prevActivity); } } else { task.mBackGestureStarted = false; diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java index 08a9da467162..dbc08cd5d1a9 100644 --- a/services/core/java/com/android/server/wm/ConfigurationContainer.java +++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java @@ -190,6 +190,14 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { * @see #mFullConfiguration */ public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) { + updateRequestedOverrideConfiguration(overrideConfiguration); + // Update full configuration of this container and all its children. + final ConfigurationContainer parent = getParent(); + onConfigurationChanged(parent != null ? parent.getConfiguration() : Configuration.EMPTY); + } + + /** Updates override configuration without recalculate full config. */ + void updateRequestedOverrideConfiguration(Configuration overrideConfiguration) { // Pre-compute this here, so we don't need to go through the entire Configuration when // writing to proto (which has significant cost if we write a lot of empty configurations). mHasOverrideConfiguration = !Configuration.EMPTY.equals(overrideConfiguration); @@ -199,9 +207,6 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { && diffRequestedOverrideMaxBounds(newBounds) != BOUNDS_CHANGE_NONE) { mRequestedOverrideConfiguration.windowConfiguration.setMaxBounds(newBounds); } - // Update full configuration of this container and all its children. - final ConfigurationContainer parent = getParent(); - onConfigurationChanged(parent != null ? parent.getConfiguration() : Configuration.EMPTY); } /** diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java index 5919806ae7e1..c18377d76cb7 100644 --- a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java @@ -23,6 +23,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; +import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER; import static android.window.DisplayAreaOrganizer.FEATURE_FULLSCREEN_MAGNIFICATION; @@ -139,7 +140,8 @@ public abstract class DisplayAreaPolicy { .addFeature(new Feature.Builder(wmService.mPolicy, "OneHanded", FEATURE_ONE_HANDED) .all() - .except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL) + .except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL, + TYPE_SECURE_SYSTEM_OVERLAY) .build()); } rootHierarchy diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 566ed6076526..2d7d7055a03b 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -138,8 +138,8 @@ import android.window.ClientWindowFrames; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.policy.ForceShowNavigationBarSettingsObserver; import com.android.internal.policy.GestureNavigationSettingsObserver; +import com.android.internal.policy.KidsModeSettingsObserver; import com.android.internal.policy.ScreenDecorationsUtils; import com.android.internal.policy.SystemBarUtils; import com.android.internal.protolog.common.ProtoLog; @@ -378,7 +378,7 @@ public class DisplayPolicy { private final WindowManagerInternal.AppTransitionListener mAppTransitionListener; - private final ForceShowNavigationBarSettingsObserver mForceShowNavigationBarSettingsObserver; + private final KidsModeSettingsObserver mKidsModeSettingsObserver; private boolean mForceShowNavigationBarEnabled; private class PolicyHandler extends Handler { @@ -653,17 +653,17 @@ public class DisplayPolicy { }); mHandler.post(mGestureNavigationSettingsObserver::register); - mForceShowNavigationBarSettingsObserver = new ForceShowNavigationBarSettingsObserver( + mKidsModeSettingsObserver = new KidsModeSettingsObserver( mHandler, mContext); - mForceShowNavigationBarSettingsObserver.setOnChangeRunnable(() -> { + mKidsModeSettingsObserver.setOnChangeRunnable(() -> { synchronized (mLock) { mForceShowNavigationBarEnabled = - mForceShowNavigationBarSettingsObserver.isEnabled(); + mKidsModeSettingsObserver.isEnabled(); updateSystemBarAttributes(); } }); - mForceShowNavigationBarEnabled = mForceShowNavigationBarSettingsObserver.isEnabled(); - mHandler.post(mForceShowNavigationBarSettingsObserver::register); + mForceShowNavigationBarEnabled = mKidsModeSettingsObserver.isEnabled(); + mHandler.post(mKidsModeSettingsObserver::register); } /** @@ -1146,8 +1146,13 @@ public class DisplayPolicy { mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR, win, (displayFrames, windowContainer, inOutFrame) -> { if (!mNavButtonForcedVisible) { - inOutFrame.inset(win.getLayoutingAttrs( - displayFrames.mRotation).providedInternalInsets); + final Insets[] providedInternalInsets = win.getLayoutingAttrs( + displayFrames.mRotation).providedInternalInsets; + if (providedInternalInsets != null + && providedInternalInsets.length > ITYPE_NAVIGATION_BAR + && providedInternalInsets[ITYPE_NAVIGATION_BAR] != null) { + inOutFrame.inset(providedInternalInsets[ITYPE_NAVIGATION_BAR]); + } inOutFrame.inset(win.mGivenContentInsets); } }, @@ -1193,13 +1198,16 @@ public class DisplayPolicy { if (attrs.providesInsetsTypes != null) { for (@InternalInsetsType int insetsType : attrs.providesInsetsTypes) { final TriConsumer<DisplayFrames, WindowContainer, Rect> imeFrameProvider = - !attrs.providedInternalImeInsets.equals(Insets.NONE) - ? (displayFrames, windowContainer, inOutFrame) -> { - inOutFrame.inset(win.getLayoutingAttrs( - displayFrames.mRotation) - .providedInternalImeInsets); - } - : null; + (displayFrames, windowContainer, inOutFrame) -> { + final Insets[] providedInternalImeInsets = + win.getLayoutingAttrs(displayFrames.mRotation) + .providedInternalImeInsets; + if (providedInternalImeInsets != null + && providedInternalImeInsets.length > insetsType + && providedInternalImeInsets[insetsType] != null) { + inOutFrame.inset(providedInternalImeInsets[insetsType]); + } + }; switch (insetsType) { case ITYPE_STATUS_BAR: mStatusBarAlt = win; @@ -1220,8 +1228,13 @@ public class DisplayPolicy { } mDisplayContent.setInsetProvider(insetsType, win, (displayFrames, windowContainer, inOutFrame) -> { - inOutFrame.inset(win.getLayoutingAttrs( - displayFrames.mRotation).providedInternalInsets); + final Insets[] providedInternalInsets = win.getLayoutingAttrs( + displayFrames.mRotation).providedInternalInsets; + if (providedInternalInsets != null + && providedInternalInsets.length > insetsType + && providedInternalInsets[insetsType] != null) { + inOutFrame.inset(providedInternalInsets[insetsType]); + } inOutFrame.inset(win.mGivenContentInsets); }, imeFrameProvider); mInsetsSourceWindowsExceptIme.add(win); @@ -1937,15 +1950,23 @@ public class DisplayPolicy { && lp.paramsForRotation[rotation] != null) { lp = lp.paramsForRotation[rotation]; } + final Insets providedInternalInsets; + if (lp.providedInternalInsets != null + && lp.providedInternalInsets.length > ITYPE_NAVIGATION_BAR + && lp.providedInternalInsets[ITYPE_NAVIGATION_BAR] != null) { + providedInternalInsets = lp.providedInternalInsets[ITYPE_NAVIGATION_BAR]; + } else { + providedInternalInsets = Insets.NONE; + } if (position == NAV_BAR_LEFT) { - if (lp.width > lp.providedInternalInsets.right) { - return lp.width - lp.providedInternalInsets.right; + if (lp.width > providedInternalInsets.right) { + return lp.width - providedInternalInsets.right; } else { return 0; } } else if (position == NAV_BAR_RIGHT) { - if (lp.width > lp.providedInternalInsets.left) { - return lp.width - lp.providedInternalInsets.left; + if (lp.width > providedInternalInsets.left) { + return lp.width - providedInternalInsets.left; } else { return 0; } @@ -1994,10 +2015,18 @@ public class DisplayPolicy { return 0; } LayoutParams lp = mNavigationBar.getLayoutingAttrs(rotation); - if (lp.height < lp.providedInternalInsets.top) { + final Insets providedInternalInsets; + if (lp.providedInternalInsets != null + && lp.providedInternalInsets.length > ITYPE_NAVIGATION_BAR + && lp.providedInternalInsets[ITYPE_NAVIGATION_BAR] != null) { + providedInternalInsets = lp.providedInternalInsets[ITYPE_NAVIGATION_BAR]; + } else { + providedInternalInsets = Insets.NONE; + } + if (lp.height < providedInternalInsets.top) { return 0; } - return lp.height - lp.providedInternalInsets.top; + return lp.height - providedInternalInsets.top; } /** @@ -2832,7 +2861,7 @@ public class DisplayPolicy { void release() { mDisplayContent.mTransitionController.unregisterLegacyListener(mAppTransitionListener); mHandler.post(mGestureNavigationSettingsObserver::unregister); - mHandler.post(mForceShowNavigationBarSettingsObserver::unregister); + mHandler.post(mKidsModeSettingsObserver::unregister); mImmersiveModeConfirmation.release(); } diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java index a7b37281842a..6162f12b516e 100644 --- a/services/core/java/com/android/server/wm/InsetsPolicy.java +++ b/services/core/java/com/android/server/wm/InsetsPolicy.java @@ -289,6 +289,23 @@ class InsetsPolicy { return adjustVisibilityForTransientTypes(originalState); } + /** + * @param type the internal type of the insets. + * @return {@code true} if the given type is controllable, {@code false} otherwise. + */ + static boolean isInsetsTypeControllable(@InternalInsetsType int type) { + switch (type) { + case ITYPE_STATUS_BAR: + case ITYPE_NAVIGATION_BAR: + case ITYPE_IME: + case ITYPE_CLIMATE_BAR: + case ITYPE_EXTRA_NAVIGATION_BAR: + return true; + default: + return false; + } + } + private static @InternalInsetsType int getInsetsTypeForLayoutParams( WindowManager.LayoutParams attrs) { @WindowManager.LayoutParams.WindowType int type = attrs.type; diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index f3f08b202fed..e04644c564f8 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -16,11 +16,7 @@ package com.android.server.wm; -import static android.view.InsetsState.ITYPE_CLIMATE_BAR; -import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_IME; -import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; -import static android.view.InsetsState.ITYPE_STATUS_BAR; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_INSETS; import static com.android.server.wm.InsetsSourceProviderProto.CAPTURED_LEASH; @@ -128,18 +124,7 @@ abstract class InsetsSourceProvider { mStateController = stateController; mFakeControl = new InsetsSourceControl( source.getType(), null /* leash */, new Point(), Insets.NONE); - - switch (source.getType()) { - case ITYPE_STATUS_BAR: - case ITYPE_NAVIGATION_BAR: - case ITYPE_IME: - case ITYPE_CLIMATE_BAR: - case ITYPE_EXTRA_NAVIGATION_BAR: - mControllable = true; - break; - default: - mControllable = false; - } + mControllable = InsetsPolicy.isInsetsTypeControllable(source.getType()); } InsetsSource getSource() { diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index fc407e616bd9..efe617d86d4e 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -445,7 +445,7 @@ public class RecentsAnimationController implements DeathRecipient { } final int taskCount = visibleTasks.size(); - for (int i = 0; i < taskCount; i++) { + for (int i = taskCount - 1; i >= 0; i--) { final Task task = visibleTasks.get(i); if (skipAnimation(task)) { continue; @@ -746,7 +746,7 @@ public class RecentsAnimationController implements DeathRecipient { ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "collectTaskRemoteAnimations, target: %s", target); } - }, true); + }, false /* traverseTopToBottom */); } void logRecentsAnimationStartTime(int durationMs) { diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index cc99f377bfee..22714c6f5593 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -24,6 +24,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE; import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK; +import static android.content.res.Configuration.EMPTY; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; @@ -2005,7 +2006,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // of the activity entering PIP r.getDisplayContent().prepareAppTransition(TRANSIT_NONE); - final boolean singleActivity = task.getChildCount() == 1; + final TaskFragment organizedTf = r.getOrganizedTaskFragment(); + final boolean singleActivity = task.getNonFinishingActivityCount() == 1; final Task rootTask; if (singleActivity) { rootTask = task; @@ -2041,6 +2043,14 @@ class RootWindowContainer extends WindowContainer<DisplayContent> task.clearLastRecentsAnimationTransaction(false /* forceRemoveOverlay */); } + // The organized TaskFragment is becoming empty because this activity is reparented + // to a new PIP Task. In this case, we should notify the organizer about why the + // TaskFragment becomes empty. + if (organizedTf != null && organizedTf.getNonFinishingActivityCount() == 1 + && organizedTf.getTopNonFinishingActivity() == r) { + organizedTf.mClearedTaskFragmentForPip = true; + } + // There are multiple activities in the task and moving the top activity should // reveal/leave the other activities in their original task. // On the other hand, ActivityRecord#onParentChanged takes care of setting the @@ -2086,6 +2096,15 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // TODO(task-org): Figure-out more structured way to do this long term. r.setWindowingMode(intermediateWindowingMode); r.mWaitForEnteringPinnedMode = true; + rootTask.forAllTaskFragments(tf -> { + // When the Task is entering picture-in-picture, we should clear all override from + // the client organizer, so the PIP activity can get the correct config from the + // Task, and prevent conflict with the PipTaskOrganizer. + if (tf.isOrganizedTaskFragment()) { + tf.resetAdjacentTaskFragment(); + tf.updateRequestedOverrideConfiguration(EMPTY); + } + }); rootTask.setWindowingMode(WINDOWING_MODE_PINNED); // Set the launch bounds for launch-into-pip Activity on the root task. if (r.getOptions() != null && r.getOptions().isLaunchIntoPip()) { @@ -2096,6 +2115,13 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // Reset the state that indicates it can enter PiP while pausing after we've moved it // to the root pinned task r.supportsEnterPipOnTaskSwitch = false; + + if (organizedTf != null && organizedTf.mClearedTaskFragmentForPip) { + // Dispatch the pending info to TaskFragmentOrganizer before PIP animation. + // Otherwise, it will keep waiting for the empty TaskFragment to be non-empty. + mService.mTaskFragmentOrganizerController.dispatchPendingInfoChangedEvent( + organizedTf); + } } finally { mService.continueWindowLayout(); } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index a46544d6c902..9ea566ece6ec 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -2035,7 +2035,7 @@ class Task extends TaskFragment { Rect outOverrideBounds = getResolvedOverrideConfiguration().windowConfiguration.getBounds(); if (windowingMode == WINDOWING_MODE_FULLSCREEN) { - if (!mCreatedByOrganizer) { + if (!isOrganized()) { // Use empty bounds to indicate "fill parent". outOverrideBounds.setEmpty(); } @@ -2780,9 +2780,11 @@ class Task extends TaskFragment { } final Rect visibleFrame = sTmpBounds; + final WindowManager.LayoutParams attrs = win.mAttrs; visibleFrame.set(win.getFrame()); visibleFrame.inset(win.getInsetsStateWithVisibilityOverride().calculateVisibleInsets( - visibleFrame, win.mAttrs.softInputMode)); + visibleFrame, attrs.type, win.getWindowingMode(), attrs.softInputMode, + attrs.flags)); out.union(visibleFrame); } diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index b96b461f2da5..e0346544d528 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -193,6 +193,12 @@ class TaskFragment extends WindowContainer<WindowContainer> { boolean mClearedTaskForReuse; /** + * The last running activity of the TaskFragment was reparented to a different Task because it + * is entering PiP. + */ + boolean mClearedTaskFragmentForPip; + + /** * When we are in the process of pausing an activity, before starting the * next one, this variable holds the activity that is currently being paused. * @@ -339,7 +345,7 @@ class TaskFragment extends WindowContainer<WindowContainer> { } } - private void resetAdjacentTaskFragment() { + void resetAdjacentTaskFragment() { // Reset the adjacent TaskFragment if its adjacent TaskFragment is also this TaskFragment. if (mAdjacentTaskFragment != null && mAdjacentTaskFragment.mAdjacentTaskFragment == this) { mAdjacentTaskFragment.mAdjacentTaskFragment = null; @@ -847,6 +853,16 @@ class TaskFragment extends WindowContainer<WindowContainer> { return getActivity((r) -> r.canBeTopRunning() && r.getTask() == this.getTask()); } + int getNonFinishingActivityCount() { + final int[] runningActivityCount = new int[1]; + forAllActivities(a -> { + if (!a.finishing) { + runningActivityCount[0]++; + } + }); + return runningActivityCount[0]; + } + boolean isTopActivityFocusable() { final ActivityRecord r = topRunningActivity(); return r != null ? r.isFocusable() @@ -1018,19 +1034,19 @@ class TaskFragment extends WindowContainer<WindowContainer> { // If the top activity is the resumed one, nothing to do. if (mResumedActivity == next && next.isState(RESUMED) && taskDisplayArea.allResumedActivitiesComplete()) { + // Ensure the visibility gets updated before execute app transition. + taskDisplayArea.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, + false /* preserveWindows */, true /* notifyClients */); // Make sure we have executed any pending transitions, since there // should be nothing left to do at this point. executeAppTransition(options); - // For devices that are not in fullscreen mode (e.g. freeform windows), it's possible - // we still want to check if the visibility of other windows have changed (e.g. bringing - // a fullscreen window forward to cover another freeform activity.) - if (taskDisplayArea.inMultiWindowMode()) { - if (taskDisplayArea.mDisplayContent != null - && taskDisplayArea.mDisplayContent.mFocusedApp != next) { - taskDisplayArea.mDisplayContent.setFocusedApp(next); - } - taskDisplayArea.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, - false /* preserveWindows */, true /* notifyClients */); + + // In a multi-resumed environment, like in a freeform device, the top + // activity can be resumed, but it might not be the focused app. + // Set focused app when top activity is resumed + if (taskDisplayArea.inMultiWindowMode() && taskDisplayArea.mDisplayContent != null + && taskDisplayArea.mDisplayContent.mFocusedApp != next) { + taskDisplayArea.mDisplayContent.setFocusedApp(next); } ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Top activity " + "resumed %s", next); @@ -1709,6 +1725,7 @@ class TaskFragment extends WindowContainer<WindowContainer> { void addChild(WindowContainer child, int index) { ActivityRecord r = topRunningActivity(); mClearedTaskForReuse = false; + mClearedTaskFragmentForPip = false; boolean isAddingActivity = child.asActivityRecord() != null; final Task task = isAddingActivity ? getTask() : null; @@ -2253,22 +2270,16 @@ class TaskFragment extends WindowContainer<WindowContainer> { } final Point positionInParent = new Point(); getRelativePosition(positionInParent); - final int[] runningActivityCount = new int[1]; - forAllActivities(a -> { - if (!a.finishing) { - runningActivityCount[0]++; - } - }); return new TaskFragmentInfo( mFragmentToken, mRemoteToken.toWindowContainerToken(), getConfiguration(), - runningActivityCount[0] == 0, - runningActivityCount[0], + getNonFinishingActivityCount(), isVisible(), childActivities, positionInParent, - mClearedTaskForReuse); + mClearedTaskForReuse, + mClearedTaskFragmentForPip); } @Nullable @@ -2317,6 +2328,14 @@ class TaskFragment extends WindowContainer<WindowContainer> { mMinHeight = minHeight; } + /** + * Whether this is an embedded TaskFragment in PIP Task. We don't allow any client config + * override for such TaskFragment to prevent flight with PipTaskOrganizer. + */ + boolean isEmbeddedTaskFragmentInPip() { + return isOrganizedTaskFragment() && getTask() != null && getTask().inPinnedWindowingMode(); + } + boolean shouldRemoveSelfOnLastChildRemoval() { return !mCreatedByOrganizer || mIsRemovalRequested; } diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index 8a0ae65267a3..9bf988f16090 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -38,6 +38,7 @@ import android.os.Parcel; import android.os.RemoteException; import android.util.Slog; import android.util.proto.ProtoOutputStream; +import android.view.Display; import android.view.SurfaceControl; import android.window.ITaskOrganizer; import android.window.ITaskOrganizerController; @@ -526,17 +527,17 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { } final StartingWindowRemovalInfo removalInfo = new StartingWindowRemovalInfo(); removalInfo.taskId = task.mTaskId; - removalInfo.playRevealAnimation = prepareAnimation; + removalInfo.playRevealAnimation = prepareAnimation + && task.getDisplayInfo().state == Display.STATE_ON; final boolean playShiftUpAnimation = !task.inMultiWindowMode(); final ActivityRecord topActivity = task.topActivityContainsStartingWindow(); if (topActivity != null) { removalInfo.deferRemoveForIme = topActivity.mDisplayContent .mayImeShowOnLaunchingActivity(topActivity); - if (prepareAnimation && playShiftUpAnimation) { + if (removalInfo.playRevealAnimation && playShiftUpAnimation) { final WindowState mainWindow = topActivity.findMainWindow(false/* includeStartingApp */); if (mainWindow != null) { - final SurfaceControl.Transaction t = mainWindow.getPendingTransaction(); removalInfo.windowAnimationLeash = applyStartingWindowAnimation(mainWindow); removalInfo.mainFrame = mainWindow.getRelativeFrame(); } diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index c44f08cbd1eb..f6f9020555d8 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -426,6 +426,21 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe t.setLayer(targetLeash, target.getLastLayer()); target.getRelativePosition(tmpPos); t.setPosition(targetLeash, tmpPos.x, tmpPos.y); + final Rect clipRect; + // No need to clip the display in case seeing the clipped content when during the + // display rotation. + if (target.asDisplayContent() != null) { + clipRect = null; + } else if (target.asActivityRecord() != null) { + // Always use parent bounds of activity because letterbox area (e.g. fixed + // aspect ratio or size compat mode) should be included. + clipRect = target.getParent().getRequestedOverrideBounds(); + clipRect.offset(-tmpPos.x, -tmpPos.y); + } else { + clipRect = target.getRequestedOverrideBounds(); + clipRect.offset(-tmpPos.x, -tmpPos.y); + } + t.setCrop(targetLeash, clipRect); t.setCornerRadius(targetLeash, 0); t.setShadowRadius(targetLeash, 0); t.setMatrix(targetLeash, 1, 0, 0, 1); diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 5969e856a56b..f5af2b4e29fa 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -236,6 +236,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< */ private boolean mCommittedReparentToAnimationLeash; + private int mSyncTransactionCommitCallbackDepth = 0; + /** Interface for {@link #isAnimating} to check which cases for the container is animating. */ public interface AnimationFlags { /** @@ -2688,6 +2690,9 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< * {@link #getPendingTransaction()} */ public Transaction getSyncTransaction() { + if (mSyncTransactionCommitCallbackDepth > 0) { + return mSyncTransaction; + } if (mSyncState != SYNC_STATE_NONE) { return mSyncTransaction; } @@ -2761,7 +2766,10 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< boolean canStartChangeTransition() { return !mWmService.mDisableTransitionAnimation && mDisplayContent != null && getSurfaceControl() != null && !mDisplayContent.inTransition() - && isVisible() && isVisibleRequested() && okToAnimate(); + && isVisible() && isVisibleRequested() && okToAnimate() + // Pip animation will be handled by PipTaskOrganizer. + && !inPinnedWindowingMode() && getParent() != null + && !getParent().inPinnedWindowingMode(); } /** @@ -3860,7 +3868,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< @AnimationType int type, @Nullable AnimationAdapter snapshotAnim); } - void addTrustedOverlay(SurfaceControlViewHost.SurfacePackage overlay) { + void addTrustedOverlay(SurfaceControlViewHost.SurfacePackage overlay, + @Nullable WindowState initialWindowState) { if (mOverlayHost == null) { mOverlayHost = new TrustedOverlayHost(mWmService); } @@ -3876,6 +3885,20 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< "Error sending initial configuration change to WindowContainer overlay"); removeTrustedOverlay(overlay); } + + // Emit an initial WindowState so that proper insets are available to overlay views + // shortly after the overlay is added. + if (initialWindowState != null) { + final InsetsState insetsState = initialWindowState.getInsetsState(); + final Rect dispBounds = getBounds(); + try { + overlay.getRemoteInterface().onInsetsChanged(insetsState, dispBounds); + } catch (Exception e) { + ProtoLog.e(WM_DEBUG_ANIM, + "Error sending initial insets change to WindowContainer overlay"); + removeTrustedOverlay(overlay); + } + } } void removeTrustedOverlay(SurfaceControlViewHost.SurfacePackage overlay) { @@ -3891,4 +3914,29 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< p.updateOverlayInsetsState(originalChange); } } + + void waitForSyncTransactionCommit(ArraySet<WindowContainer> wcAwaitingCommit) { + if (wcAwaitingCommit.contains(this)) { + return; + } + mSyncTransactionCommitCallbackDepth++; + wcAwaitingCommit.add(this); + + for (int i = mChildren.size() - 1; i >= 0; --i) { + mChildren.get(i).waitForSyncTransactionCommit(wcAwaitingCommit); + } + } + + void onSyncTransactionCommitted(SurfaceControl.Transaction t) { + mSyncTransactionCommitCallbackDepth--; + if (mSyncTransactionCommitCallbackDepth > 0) { + return; + } + if (mSyncState != SYNC_STATE_NONE) { + return; + } + + t.merge(mSyncTransaction); + } + } diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java index be745966ce30..42fad6d14fb9 100644 --- a/services/core/java/com/android/server/wm/WindowManagerInternal.java +++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java @@ -409,21 +409,6 @@ public abstract class WindowManagerInternal { public abstract void getMagnificationRegion(int displayId, @NonNull Region magnificationRegion); /** - * Gets the magnification and translation applied to a window given its token. - * Not all windows are magnified and the window manager policy determines which - * windows are magnified. The returned result also takes into account the compat - * scale if necessary. - * - * @param windowToken The window's token. - * - * @return The magnification spec for the window. - * - * @see #setMagnificationCallbacks(int, MagnificationCallbacks) - */ - public abstract MagnificationSpec getCompatibleMagnificationSpecForWindow( - IBinder windowToken); - - /** * Sets a callback for observing which windows are touchable for the purposes * of accessibility on specified display. * diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 77d31df0bee7..2f4dc515fd11 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -1976,8 +1976,10 @@ public class WindowManagerService extends IWindowManager.Stub // We use the visible frame, because we want the animation to morph the window from what // was visible to the user to the final destination of the new window. final Rect frame = new Rect(replacedWindow.getFrame()); + final WindowManager.LayoutParams attrs = replacedWindow.mAttrs; frame.inset(replacedWindow.getInsetsStateWithVisibilityOverride().calculateVisibleInsets( - frame, replacedWindow.mAttrs.softInputMode)); + frame, attrs.type, replacedWindow.getWindowingMode(), attrs.softInputMode, + attrs.flags)); // We treat this as if this activity was opening, so we can trigger the app transition // animation and piggy-back on existing transition animation infrastructure. final DisplayContent dc = activity.getDisplayContent(); @@ -7621,29 +7623,6 @@ public class WindowManagerService extends IWindowManager.Stub } @Override - public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) { - synchronized (mGlobalLock) { - WindowState windowState = mWindowMap.get(windowToken); - if (windowState == null) { - return null; - } - MagnificationSpec spec = null; - if (mAccessibilityController.hasCallbacks()) { - spec = mAccessibilityController.getMagnificationSpecForWindow(windowState); - } - if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) { - return null; - } - MagnificationSpec result = new MagnificationSpec(); - if (spec != null) { - result.setTo(spec); - } - result.scale *= windowState.mGlobalScale; - return result; - } - } - - @Override public boolean setMagnificationCallbacks(int displayId, @Nullable MagnificationCallbacks callbacks) { synchronized (mGlobalLock) { @@ -8135,7 +8114,7 @@ public class WindowManagerService extends IWindowManager.Stub if (task == null) { throw new IllegalArgumentException("no task with taskId" + taskId); } - task.addTrustedOverlay(overlay); + task.addTrustedOverlay(overlay, task.getTopVisibleAppMainWindow()); } } diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index b5cf708eb46d..67f7ff701981 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -677,15 +677,21 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } case HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT: { final IBinder fragmentToken = hop.getContainer(); - if (!mLaunchTaskFragments.containsKey(fragmentToken)) { + final TaskFragment tf = mLaunchTaskFragments.get(fragmentToken); + if (tf == null) { final Throwable exception = new IllegalArgumentException( "Not allowed to operate with invalid fragment token"); sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); break; } + if (tf.isEmbeddedTaskFragmentInPip()) { + final Throwable exception = new IllegalArgumentException( + "Not allowed to start activity in PIP TaskFragment"); + sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); + break; + } final Intent activityIntent = hop.getActivityIntent(); final Bundle activityOptions = hop.getLaunchOptions(); - final TaskFragment tf = mLaunchTaskFragments.get(fragmentToken); final int result = mService.getActivityStartController() .startActivityInTaskFragment(tf, activityIntent, activityOptions, hop.getCallingActivity(), caller.mUid, caller.mPid); @@ -707,6 +713,12 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); break; } + if (parent.isEmbeddedTaskFragmentInPip()) { + final Throwable exception = new IllegalArgumentException( + "Not allowed to reparent activity to PIP TaskFragment"); + sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); + break; + } if (!parent.isAllowedToEmbedActivity(activity)) { final Throwable exception = new SecurityException( "The task fragment is not trusted to embed the given activity."); @@ -730,6 +742,13 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); break; } + if (tf1.isEmbeddedTaskFragmentInPip() + || (tf2 != null && tf2.isEmbeddedTaskFragmentInPip())) { + final Throwable exception = new IllegalArgumentException( + "Not allowed to set adjacent on TaskFragment in PIP Task"); + sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); + break; + } tf1.setAdjacentTaskFragment(tf2, false /* moveAdjacentTogether */); effects |= TRANSACT_EFFECTS_LIFECYCLE; @@ -1092,6 +1111,10 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub throw new IllegalArgumentException("setAdjacentRootsHierarchyOp: Not created by" + " organizer root1=" + root1 + " root2=" + root2); } + if (root1.isEmbeddedTaskFragmentInPip() || root2.isEmbeddedTaskFragmentInPip()) { + Slog.e(TAG, "Attempt to set adjacent TaskFragment in PIP Task"); + return 0; + } root1.setAdjacentTaskFragment(root2, hop.getMoveAdjacentTogether()); return TRANSACT_EFFECTS_LIFECYCLE; } @@ -1105,6 +1128,10 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub private int applyWindowContainerChange(WindowContainer wc, WindowContainerTransaction.Change c) { sanitizeWindowContainer(wc); + if (wc.asTaskFragment() != null && wc.asTaskFragment().isEmbeddedTaskFragmentInPip()) { + // No override from organizer for embedded TaskFragment in a PIP Task. + return 0; + } int effects = applyChanges(wc, c); @@ -1420,21 +1447,28 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub return; } // The ownerActivity has to belong to the same app as the target Task. - if (ownerActivity.getTask().effectiveUid != ownerActivity.getUid() - || ownerActivity.getTask().effectiveUid != caller.mUid) { + final Task ownerTask = ownerActivity.getTask(); + if (ownerTask.effectiveUid != ownerActivity.getUid() + || ownerTask.effectiveUid != caller.mUid) { final Throwable exception = new SecurityException("Not allowed to operate with the ownerToken while " + "the root activity of the target task belong to the different app"); sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); return; } + if (ownerTask.inPinnedWindowingMode()) { + final Throwable exception = new IllegalArgumentException( + "Not allowed to create TaskFragment in PIP Task"); + sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); + return; + } final TaskFragment taskFragment = new TaskFragment(mService, creationParams.getFragmentToken(), true /* createdByOrganizer */); // Set task fragment organizer immediately, since it might have to be notified about further // actions. taskFragment.setTaskFragmentOrganizer(creationParams.getOrganizer(), ownerActivity.getUid(), ownerActivity.info.processName); - ownerActivity.getTask().addChild(taskFragment, POSITION_TOP); + ownerTask.addChild(taskFragment, POSITION_TOP); taskFragment.setWindowingMode(creationParams.getWindowingMode()); taskFragment.setBounds(creationParams.getInitialBounds()); mLaunchTaskFragments.put(creationParams.getFragmentToken(), taskFragment); @@ -1467,6 +1501,12 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub return; } } + if (newParentTF.isEmbeddedTaskFragmentInPip() || oldParent.isEmbeddedTaskFragmentInPip()) { + final Throwable exception = new SecurityException( + "Not allow to reparent in TaskFragment in PIP Task."); + sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); + return; + } while (oldParent.hasChild()) { oldParent.getChildAt(0).reparent(newParentTF, POSITION_TOP); } @@ -1482,6 +1522,15 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); return 0; } + if (taskFragment.isEmbeddedTaskFragmentInPip() + // When the Task enters PiP before the organizer removes the empty TaskFragment, we + // should allow it to do the cleanup. + && taskFragment.getTopNonFinishingActivity() != null) { + final Throwable exception = new IllegalArgumentException( + "Not allowed to delete TaskFragment in PIP Task"); + sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); + return 0; + } mLaunchTaskFragments.removeAt(index); taskFragment.remove(true /* withTransition */, "deleteTaskFragment"); return TRANSACT_EFFECTS_LIFECYCLE; diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index e7d4877ce514..238f96ffd1e1 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1851,7 +1851,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP bounds.set(mWindowFrames.mFrame); bounds.inset(getInsetsStateWithVisibilityOverride().calculateVisibleInsets( - bounds, mAttrs.softInputMode)); + bounds, mAttrs.type, getWindowingMode(), mAttrs.softInputMode, mAttrs.flags)); if (intersectWithRootTaskBounds) { bounds.intersect(mTmpRect); } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceManagementResourcesProvider.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceManagementResourcesProvider.java index 82fe8b9362b0..6aef90c79705 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceManagementResourcesProvider.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceManagementResourcesProvider.java @@ -55,8 +55,6 @@ class DeviceManagementResourcesProvider { private static final String TAG_ROOT = "root"; private static final String TAG_DRAWABLE_STYLE_ENTRY = "drawable-style-entry"; private static final String TAG_DRAWABLE_SOURCE_ENTRY = "drawable-source-entry"; - private static final String ATTR_DRAWABLE_STYLE_SIZE = "drawable-style-size"; - private static final String ATTR_DRAWABLE_SOURCE_SIZE = "drawable-source-size"; private static final String ATTR_DRAWABLE_STYLE = "drawable-style"; private static final String ATTR_DRAWABLE_SOURCE = "drawable-source"; private static final String ATTR_DRAWABLE_ID = "drawable-id"; @@ -70,9 +68,9 @@ class DeviceManagementResourcesProvider { mUpdatedDrawablesForStyle = new HashMap<>(); /** - * Map of <drawable_id, <source_id, resource_value>> + * Map of <drawable_id, <source_id, <style_id, resource_value>>> */ - private final Map<String, Map<String, ParcelableResource>> + private final Map<String, Map<String, Map<String, ParcelableResource>>> mUpdatedDrawablesForSource = new HashMap<>(); /** @@ -110,7 +108,8 @@ class DeviceManagementResourcesProvider { if (DevicePolicyResources.UNDEFINED.equals(drawableSource)) { updated |= updateDrawable(drawableId, drawableStyle, resource); } else { - updated |= updateDrawableForSource(drawableId, drawableSource, resource); + updated |= updateDrawableForSource( + drawableId, drawableSource, drawableStyle, resource); } } if (!updated) { @@ -138,19 +137,23 @@ class DeviceManagementResourcesProvider { } } - // TODO(b/214576716): change this to respect style private boolean updateDrawableForSource( - String drawableId, String drawableSource, ParcelableResource updatableResource) { + String drawableId, String drawableSource, String drawableStyle, + ParcelableResource updatableResource) { synchronized (mLock) { + Map<String, Map<String, ParcelableResource>> drawablesForId = + mUpdatedDrawablesForSource.get(drawableId); if (!mUpdatedDrawablesForSource.containsKey(drawableId)) { mUpdatedDrawablesForSource.put(drawableId, new HashMap<>()); } - ParcelableResource current = mUpdatedDrawablesForSource.get(drawableId).get( - drawableSource); + if (!drawablesForId.containsKey(drawableSource)) { + mUpdatedDrawablesForSource.get(drawableId).put(drawableSource, new HashMap<>()); + } + ParcelableResource current = drawablesForId.get(drawableSource).get(drawableStyle); if (updatableResource.equals(current)) { return false; } - mUpdatedDrawablesForSource.get(drawableId).put(drawableSource, updatableResource); + drawablesForId.get(drawableSource).put(drawableStyle, updatableResource); return true; } } @@ -175,23 +178,30 @@ class DeviceManagementResourcesProvider { } @Nullable - ParcelableResource getDrawable( - String drawableId, String drawableStyle, String drawableSource) { + ParcelableResource getDrawable(String drawableId, String drawableStyle, String drawableSource) { synchronized (mLock) { - if (mUpdatedDrawablesForSource.containsKey(drawableId) - && mUpdatedDrawablesForSource.get(drawableId).containsKey(drawableSource)) { - return mUpdatedDrawablesForSource.get(drawableId).get(drawableSource); + ParcelableResource resource = getDrawableForSourceLocked( + drawableId, drawableStyle, drawableSource); + if (resource != null) { + return resource; } if (!mUpdatedDrawablesForStyle.containsKey(drawableId)) { - Log.d(TAG, "No updated drawable found for drawable id " + drawableId); return null; } - if (mUpdatedDrawablesForStyle.get(drawableId).containsKey(drawableStyle)) { - return mUpdatedDrawablesForStyle.get(drawableId).get(drawableStyle); - } + return mUpdatedDrawablesForStyle.get(drawableId).get(drawableStyle); + } + } + + @Nullable + ParcelableResource getDrawableForSourceLocked( + String drawableId, String drawableStyle, String drawableSource) { + if (!mUpdatedDrawablesForSource.containsKey(drawableId)) { + return null; + } + if (!mUpdatedDrawablesForSource.get(drawableId).containsKey(drawableSource)) { + return null; } - Log.d(TAG, "No updated drawable found for drawable id " + drawableId); - return null; + return mUpdatedDrawablesForSource.get(drawableId).get(drawableSource).get(drawableStyle); } /** @@ -249,12 +259,8 @@ class DeviceManagementResourcesProvider { @Nullable ParcelableResource getString(String stringId) { synchronized (mLock) { - if (mUpdatedStrings.containsKey(stringId)) { - return mUpdatedStrings.get(stringId); - } + return mUpdatedStrings.get(stringId); } - Log.d(TAG, "No updated string found for string id " + stringId); - return null; } private void write() { @@ -359,50 +365,55 @@ class DeviceManagementResourcesProvider { } void writeInner(TypedXmlSerializer out) throws IOException { + writeDrawablesForStylesInner(out); + writeDrawablesForSourcesInner(out); + writeStringsInner(out); + } + + private void writeDrawablesForStylesInner(TypedXmlSerializer out) throws IOException { if (mUpdatedDrawablesForStyle != null && !mUpdatedDrawablesForStyle.isEmpty()) { for (Map.Entry<String, Map<String, ParcelableResource>> drawableEntry : mUpdatedDrawablesForStyle.entrySet()) { - out.startTag(/* namespace= */ null, TAG_DRAWABLE_STYLE_ENTRY); - out.attribute( - /* namespace= */ null, ATTR_DRAWABLE_ID, drawableEntry.getKey()); - out.attributeInt( - /* namespace= */ null, - ATTR_DRAWABLE_STYLE_SIZE, - drawableEntry.getValue().size()); - int counter = 0; for (Map.Entry<String, ParcelableResource> styleEntry : drawableEntry.getValue().entrySet()) { + out.startTag(/* namespace= */ null, TAG_DRAWABLE_STYLE_ENTRY); + out.attribute( + /* namespace= */ null, ATTR_DRAWABLE_ID, drawableEntry.getKey()); out.attribute( /* namespace= */ null, - ATTR_DRAWABLE_STYLE + (counter++), + ATTR_DRAWABLE_STYLE, styleEntry.getKey()); styleEntry.getValue().writeToXmlFile(out); + out.endTag(/* namespace= */ null, TAG_DRAWABLE_STYLE_ENTRY); } - out.endTag(/* namespace= */ null, TAG_DRAWABLE_STYLE_ENTRY); } } + } + + private void writeDrawablesForSourcesInner(TypedXmlSerializer out) throws IOException { if (mUpdatedDrawablesForSource != null && !mUpdatedDrawablesForSource.isEmpty()) { - for (Map.Entry<String, Map<String, ParcelableResource>> drawableEntry + for (Map.Entry<String, Map<String, Map<String, ParcelableResource>>> drawableEntry : mUpdatedDrawablesForSource.entrySet()) { - out.startTag(/* namespace= */ null, TAG_DRAWABLE_SOURCE_ENTRY); - out.attribute( - /* namespace= */ null, ATTR_DRAWABLE_ID, drawableEntry.getKey()); - out.attributeInt( - /* namespace= */ null, - ATTR_DRAWABLE_SOURCE_SIZE, - drawableEntry.getValue().size()); - int counter = 0; - for (Map.Entry<String, ParcelableResource> sourceEntry + for (Map.Entry<String, Map<String, ParcelableResource>> sourceEntry : drawableEntry.getValue().entrySet()) { - out.attribute( - /* namespace= */ null, - ATTR_DRAWABLE_SOURCE + (counter++), - sourceEntry.getKey()); - sourceEntry.getValue().writeToXmlFile(out); + for (Map.Entry<String, ParcelableResource> styleEntry + : sourceEntry.getValue().entrySet()) { + out.startTag(/* namespace= */ null, TAG_DRAWABLE_SOURCE_ENTRY); + out.attribute(/* namespace= */ null, ATTR_DRAWABLE_ID, + drawableEntry.getKey()); + out.attribute(/* namespace= */ null, ATTR_DRAWABLE_SOURCE, + sourceEntry.getKey()); + out.attribute(/* namespace= */ null, ATTR_DRAWABLE_STYLE, + styleEntry.getKey()); + styleEntry.getValue().writeToXmlFile(out); + out.endTag(/* namespace= */ null, TAG_DRAWABLE_SOURCE_ENTRY); + } } - out.endTag(/* namespace= */ null, TAG_DRAWABLE_SOURCE_ENTRY); } } + } + + private void writeStringsInner(TypedXmlSerializer out) throws IOException { if (mUpdatedStrings != null && !mUpdatedStrings.isEmpty()) { for (Map.Entry<String, ParcelableResource> entry : mUpdatedStrings.entrySet()) { @@ -417,52 +428,48 @@ class DeviceManagementResourcesProvider { } } - private boolean readInner( - TypedXmlPullParser parser, int depth, String tag) + private boolean readInner(TypedXmlPullParser parser, int depth, String tag) throws XmlPullParserException, IOException { if (depth > 2) { return true; // Ignore } switch (tag) { - case TAG_DRAWABLE_STYLE_ENTRY: - String drawableId = parser.getAttributeValue( - /* namespace= */ null, ATTR_DRAWABLE_ID); - mUpdatedDrawablesForStyle.put( - drawableId, - new HashMap<>()); - int size = parser.getAttributeInt( - /* namespace= */ null, ATTR_DRAWABLE_STYLE_SIZE); - for (int i = 0; i < size; i++) { - String style = parser.getAttributeValue( - /* namespace= */ null, ATTR_DRAWABLE_STYLE + i); - mUpdatedDrawablesForStyle.get(drawableId).put( - style, - ParcelableResource.createFromXml(parser)); + case TAG_DRAWABLE_STYLE_ENTRY: { + String id = parser.getAttributeValue(/* namespace= */ null, ATTR_DRAWABLE_ID); + String style = parser.getAttributeValue( + /* namespace= */ null, ATTR_DRAWABLE_STYLE); + ParcelableResource resource = ParcelableResource.createFromXml(parser); + if (!mUpdatedDrawablesForStyle.containsKey(id)) { + mUpdatedDrawablesForStyle.put(id, new HashMap<>()); } + mUpdatedDrawablesForStyle.get(id).put(style, resource); break; - case TAG_DRAWABLE_SOURCE_ENTRY: - drawableId = parser.getAttributeValue( - /* namespace= */ null, ATTR_DRAWABLE_ID); - mUpdatedDrawablesForSource.put(drawableId, new HashMap<>()); - size = parser.getAttributeInt( - /* namespace= */ null, ATTR_DRAWABLE_SOURCE_SIZE); - for (int i = 0; i < size; i++) { - String source = parser.getAttributeValue( - /* namespace= */ null, ATTR_DRAWABLE_SOURCE + i); - mUpdatedDrawablesForSource.get(drawableId).put( - source, - ParcelableResource.createFromXml(parser)); + } + case TAG_DRAWABLE_SOURCE_ENTRY: { + String id = parser.getAttributeValue(/* namespace= */ null, ATTR_DRAWABLE_ID); + String source = parser.getAttributeValue( + /* namespace= */ null, ATTR_DRAWABLE_SOURCE); + String style = parser.getAttributeValue( + /* namespace= */ null, ATTR_DRAWABLE_STYLE); + ParcelableResource resource = ParcelableResource.createFromXml(parser); + if (!mUpdatedDrawablesForSource.containsKey(id)) { + mUpdatedDrawablesForSource.put(id, new HashMap<>()); + } + if (!mUpdatedDrawablesForSource.get(id).containsKey(source)) { + mUpdatedDrawablesForSource.get(id).put(source, new HashMap<>()); } + mUpdatedDrawablesForSource.get(id).get(source).put(style, resource); break; - case TAG_STRING_ENTRY: - String sourceId = parser.getAttributeValue( - /* namespace= */ null, ATTR_SOURCE_ID); - mUpdatedStrings.put( - sourceId, ParcelableResource.createFromXml(parser)); + } + case TAG_STRING_ENTRY: { + String id = parser.getAttributeValue(/* namespace= */ null, ATTR_SOURCE_ID); + mUpdatedStrings.put(id, ParcelableResource.createFromXml(parser)); break; - default: + } + default: { Log.e(TAG, "Unexpected tag: " + tag); return false; + } } return true; } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 268d588bd907..18bffebb427c 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -382,8 +382,6 @@ import com.android.server.uri.UriGrantsManagerInternal; import com.android.server.utils.Slogf; import com.android.server.wm.ActivityTaskManagerInternal; -import com.google.android.collect.Sets; - import org.xmlpull.v1.XmlPullParserException; import java.io.ByteArrayInputStream; @@ -1781,7 +1779,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @VisibleForTesting DevicePolicyManagerService(Injector injector) { - DevicePolicyManager.disableGetKeyguardDisabledFeaturesCache(); + DevicePolicyManager.disableLocalCaches(); mInjector = injector; mContext = Objects.requireNonNull(injector.mContext); @@ -2002,7 +2000,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { synchronized (getLockObject()) { mOwners.load(); setDeviceOwnershipSystemPropertyLocked(); - findOwnerComponentIfNecessaryLocked(); } } @@ -2387,139 +2384,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } - private void findOwnerComponentIfNecessaryLocked() { - if (!mOwners.hasDeviceOwner()) { - return; - } - final ComponentName doComponentName = mOwners.getDeviceOwnerComponent(); - - if (!TextUtils.isEmpty(doComponentName.getClassName())) { - return; // Already a full component name. - } - - final ComponentName doComponent = findAdminComponentWithPackageLocked( - doComponentName.getPackageName(), - mOwners.getDeviceOwnerUserId()); - if (doComponent == null) { - Slogf.e(LOG_TAG, "Device-owner isn't registered as device-admin"); - } else { - mOwners.setDeviceOwnerWithRestrictionsMigrated( - doComponent, - mOwners.getDeviceOwnerName(), - mOwners.getDeviceOwnerUserId(), - !mOwners.getDeviceOwnerUserRestrictionsNeedsMigration()); - mOwners.writeDeviceOwner(); - if (VERBOSE_LOG) { - Slogf.v(LOG_TAG, "Device owner component filled in"); - } - } - } - - /** - * We didn't use to persist user restrictions for each owners but only persisted in user - * manager. - */ - private void migrateUserRestrictionsIfNecessaryLocked() { - boolean migrated = false; - // Migrate for the DO. Basically all restrictions should be considered to be set by DO, - // except for the "system controlled" ones. - if (mOwners.getDeviceOwnerUserRestrictionsNeedsMigration()) { - if (VERBOSE_LOG) { - Slogf.v(LOG_TAG, "Migrating DO user restrictions"); - } - migrated = true; - - // Migrate user 0 restrictions to DO. - final ActiveAdmin deviceOwnerAdmin = getDeviceOwnerAdminLocked(); - - migrateUserRestrictionsForUser(UserHandle.SYSTEM, deviceOwnerAdmin, - /* exceptionList =*/ null, /* isDeviceOwner =*/ true); - - // Push DO user restrictions to user manager. - pushUserRestrictions(UserHandle.USER_SYSTEM); - - mOwners.setDeviceOwnerUserRestrictionsMigrated(); - } - - // Migrate for POs. - - // The following restrictions can be set on secondary users by the device owner, so we - // assume they're not from the PO. - final Set<String> secondaryUserExceptionList = Sets.newArraySet( - UserManager.DISALLOW_OUTGOING_CALLS, - UserManager.DISALLOW_SMS); - - for (UserInfo ui : mUserManager.getUsers()) { - final int userId = ui.id; - if (mOwners.getProfileOwnerUserRestrictionsNeedsMigration(userId)) { - if (VERBOSE_LOG) { - Slogf.v(LOG_TAG, "Migrating PO user restrictions for user %d", userId); - } - migrated = true; - - final ActiveAdmin profileOwnerAdmin = getProfileOwnerAdminLocked(userId); - - final Set<String> exceptionList = - (userId == UserHandle.USER_SYSTEM) ? null : secondaryUserExceptionList; - - migrateUserRestrictionsForUser(ui.getUserHandle(), profileOwnerAdmin, - exceptionList, /* isDeviceOwner =*/ false); - - // Note if a secondary user has no PO but has a DA that disables camera, we - // don't get here and won't push the camera user restriction to UserManager - // here. That's okay because we'll push user restrictions anyway when a user - // starts. But we still do it because we want to let user manager persist - // upon migration. - pushUserRestrictions(userId); - - mOwners.setProfileOwnerUserRestrictionsMigrated(userId); - } - } - if (VERBOSE_LOG && migrated) { - Slogf.v(LOG_TAG, "User restrictions migrated."); - } - } - - private void migrateUserRestrictionsForUser(UserHandle user, ActiveAdmin admin, - Set<String> exceptionList, boolean isDeviceOwner) { - final Bundle origRestrictions = mUserManagerInternal.getBaseUserRestrictions( - user.getIdentifier()); - - final Bundle newBaseRestrictions = new Bundle(); - final Bundle newOwnerRestrictions = new Bundle(); - - for (String key : origRestrictions.keySet()) { - if (!origRestrictions.getBoolean(key)) { - continue; - } - final boolean canOwnerChange = isDeviceOwner - ? UserRestrictionsUtils.canDeviceOwnerChange(key) - : UserRestrictionsUtils.canProfileOwnerChange(key, user.getIdentifier()); - - if (!canOwnerChange || (exceptionList!= null && exceptionList.contains(key))) { - newBaseRestrictions.putBoolean(key, true); - } else { - newOwnerRestrictions.putBoolean(key, true); - } - } - - if (VERBOSE_LOG) { - Slogf.v(LOG_TAG, "origRestrictions=%s", origRestrictions); - Slogf.v(LOG_TAG, "newBaseRestrictions=%s", newBaseRestrictions); - Slogf.v(LOG_TAG, "newOwnerRestrictions=%s", newOwnerRestrictions); - } - mUserManagerInternal.setBaseUserRestrictionsByDpmsForMigration(user.getIdentifier(), - newBaseRestrictions); - - if (admin != null) { - admin.ensureUserRestrictions().clear(); - admin.ensureUserRestrictions().putAll(newOwnerRestrictions); - } else { - Slogf.w(LOG_TAG, "ActiveAdmin for DO/PO not found. user=" + user.getIdentifier()); - } - saveSettingsLocked(user.getIdentifier()); - } - /** * Fix left-over restrictions and auto-time policy during COMP -> COPE migration. * @@ -2555,27 +2419,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } - private ComponentName findAdminComponentWithPackageLocked(String packageName, int userId) { - final DevicePolicyData policy = getUserData(userId); - final int n = policy.mAdminList.size(); - ComponentName found = null; - int nFound = 0; - for (int i = 0; i < n; i++) { - final ActiveAdmin admin = policy.mAdminList.get(i); - if (packageName.equals(admin.info.getPackageName())) { - // Found! - if (nFound == 0) { - found = admin.info.getComponent(); - } - nFound++; - } - } - if (nFound > 1) { - Slogf.w(LOG_TAG, "Multiple DA found; assume the first one is DO."); - } - return found; - } - /** * Set an alarm for an upcoming event - expiration warning, expiration, or post-expiration * reminders. Clears alarm if no expirations are configured. @@ -3197,7 +3040,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { private void onLockSettingsReady() { synchronized (getLockObject()) { - migrateUserRestrictionsIfNecessaryLocked(); fixupAutoTimeRestrictionDuringOrganizationOwnedDeviceMigration(); } getUserData(UserHandle.USER_SYSTEM); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java index 37da7b428148..859183c80191 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java @@ -79,8 +79,6 @@ class Owners { private static final boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE - private static final String DEVICE_OWNER_XML_LEGACY = "device_owner.xml"; - // XML storing device owner info, system update policy and pending OTA update information. private static final String DEVICE_OWNER_XML = "device_owner_2.xml"; @@ -89,7 +87,6 @@ class Owners { private static final String TAG_ROOT = "root"; private static final String TAG_DEVICE_OWNER = "device-owner"; - private static final String TAG_DEVICE_INITIALIZER = "device-initializer"; private static final String TAG_SYSTEM_UPDATE_POLICY = "system-update-policy"; private static final String TAG_FREEZE_PERIOD_RECORD = "freeze-record"; private static final String TAG_PENDING_OTA_INFO = "pending-ota-info"; @@ -107,7 +104,6 @@ class Owners { private static final String ATTR_REMOTE_BUGREPORT_URI = "remoteBugreportUri"; private static final String ATTR_REMOTE_BUGREPORT_HASH = "remoteBugreportHash"; private static final String ATTR_USERID = "userId"; - private static final String ATTR_USER_RESTRICTIONS_MIGRATED = "userRestrictionsMigrated"; private static final String ATTR_FREEZE_RECORD_START = "start"; private static final String ATTR_FREEZE_RECORD_END = "end"; // Legacy attribute, its presence would mean the profile owner associated with it is @@ -180,35 +176,14 @@ class Owners { */ void load() { synchronized (mLock) { - // First, try to read from the legacy file. - final File legacy = getLegacyConfigFile(); - final List<UserInfo> users = mUserManager.getAliveUsers(); - if (readLegacyOwnerFileLocked(legacy)) { - if (DEBUG) { - Log.d(TAG, "Legacy config file found."); - } - - // Legacy file exists, write to new files and remove the legacy one. - writeDeviceOwner(); - for (int userId : getProfileOwnerKeys()) { - writeProfileOwner(userId); - } - if (DEBUG) { - Log.d(TAG, "Deleting legacy config file"); - } - if (!legacy.delete()) { - Slog.e(TAG, "Failed to remove the legacy setting file"); - } - } else { - // No legacy file, read from the new format files. - new DeviceOwnerReadWriter().readFromFileLocked(); + new DeviceOwnerReadWriter().readFromFileLocked(); - for (UserInfo ui : users) { - new ProfileOwnerReadWriter(ui.id).readFromFileLocked(); - } + for (UserInfo ui : users) { + new ProfileOwnerReadWriter(ui.id).readFromFileLocked(); } + mUserManagerInternal.setDeviceManaged(hasDeviceOwner()); for (UserInfo ui : users) { mUserManagerInternal.setUserManaged(ui.id, hasProfileOwner(ui.id)); @@ -338,23 +313,11 @@ class Owners { return; } synchronized (mLock) { - // For a newly set DO, there's no need for migration. - setDeviceOwnerWithRestrictionsMigrated(admin, ownerName, userId, - /* userRestrictionsMigrated =*/ true); - } - } - - // Note this should be only called during migration. Normally when DO is set, - // userRestrictionsMigrated should always be true. - void setDeviceOwnerWithRestrictionsMigrated(ComponentName admin, String ownerName, int userId, - boolean userRestrictionsMigrated) { - synchronized (mLock) { // A device owner is allowed to access device identifiers. Even though this flag // is not currently checked for device owner, it is set to true here so that it is // semantically compatible with the meaning of this flag. - mDeviceOwner = new OwnerInfo(ownerName, admin, userRestrictionsMigrated, - /* remoteBugreportUri =*/ null, /* remoteBugreportHash =*/ - null, /* isOrganizationOwnedDevice =*/true); + mDeviceOwner = new OwnerInfo(ownerName, admin, /* remoteBugreportUri =*/ null, + /* remoteBugreportHash =*/ null, /* isOrganizationOwnedDevice =*/ true); mDeviceOwnerUserId = userId; mUserManagerInternal.setDeviceManaged(true); @@ -385,8 +348,8 @@ class Owners { synchronized (mLock) { // For a newly set PO, there's no need for migration. mProfileOwners.put(userId, new OwnerInfo(ownerName, admin, - /* userRestrictionsMigrated =*/ true, /* remoteBugreportUri =*/ null, - /* remoteBugreportHash =*/ null, /* isOrganizationOwnedDevice =*/ false)); + /* remoteBugreportUri =*/ null, /* remoteBugreportHash =*/ null, + /* isOrganizationOwnedDevice =*/ false)); mUserManagerInternal.setUserManaged(userId, true); notifyChangeLocked(); } @@ -404,8 +367,7 @@ class Owners { synchronized (mLock) { final OwnerInfo ownerInfo = mProfileOwners.get(userId); final OwnerInfo newOwnerInfo = new OwnerInfo(target.getPackageName(), target, - ownerInfo.userRestrictionsMigrated, ownerInfo.remoteBugreportUri, - ownerInfo.remoteBugreportHash, /* isOrganizationOwnedDevice =*/ + ownerInfo.remoteBugreportUri, ownerInfo.remoteBugreportHash, ownerInfo.isOrganizationOwnedDevice); mProfileOwners.put(userId, newOwnerInfo); notifyChangeLocked(); @@ -423,10 +385,8 @@ class Owners { } // We don't set a name because it's not used anyway. // See DevicePolicyManagerService#getDeviceOwnerName - mDeviceOwner = new OwnerInfo(null, target, - mDeviceOwner.userRestrictionsMigrated, mDeviceOwner.remoteBugreportUri, - mDeviceOwner.remoteBugreportHash, /* isOrganizationOwnedDevice =*/ - mDeviceOwner.isOrganizationOwnedDevice); + mDeviceOwner = new OwnerInfo(null, target, mDeviceOwner.remoteBugreportUri, + mDeviceOwner.remoteBugreportHash, mDeviceOwner.isOrganizationOwnedDevice); if (previousDeviceOwnerType != null) { mDeviceOwnerTypes.put(mDeviceOwner.packageName, previousDeviceOwnerType); } @@ -570,35 +530,6 @@ class Owners { } } - /** - * @return true if user restrictions need to be migrated for DO. - */ - boolean getDeviceOwnerUserRestrictionsNeedsMigration() { - synchronized (mLock) { - return mDeviceOwner != null && !mDeviceOwner.userRestrictionsMigrated; - } - } - - /** - * @return true if user restrictions need to be migrated for PO. - */ - boolean getProfileOwnerUserRestrictionsNeedsMigration(int userId) { - synchronized (mLock) { - OwnerInfo profileOwner = mProfileOwners.get(userId); - return profileOwner != null && !profileOwner.userRestrictionsMigrated; - } - } - - /** Sets the user restrictions migrated flag, and also writes to the file. */ - void setDeviceOwnerUserRestrictionsMigrated() { - synchronized (mLock) { - if (mDeviceOwner != null) { - mDeviceOwner.userRestrictionsMigrated = true; - } - writeDeviceOwner(); - } - } - /** Sets the remote bugreport uri and hash, and also writes to the file. */ void setDeviceOwnerRemoteBugreportUriAndHash(String remoteBugreportUri, String remoteBugreportHash) { @@ -611,17 +542,6 @@ class Owners { } } - /** Sets the user restrictions migrated flag, and also writes to the file. */ - void setProfileOwnerUserRestrictionsMigrated(int userId) { - synchronized (mLock) { - OwnerInfo profileOwner = mProfileOwners.get(userId); - if (profileOwner != null) { - profileOwner.userRestrictionsMigrated = true; - } - writeProfileOwner(userId); - } - } - /** Set whether the profile owner manages an organization-owned device, then write to file. */ void setProfileOwnerOfOrganizationOwnedDevice(int userId, boolean isOrganizationOwnedDevice) { synchronized (mLock) { @@ -696,72 +616,6 @@ class Owners { } } - private boolean readLegacyOwnerFileLocked(File file) { - if (!file.exists()) { - // Already migrated or the device has no owners. - return false; - } - try { - InputStream input = new AtomicFile(file).openRead(); - TypedXmlPullParser parser = Xml.resolvePullParser(input); - int type; - while ((type = parser.next()) != TypedXmlPullParser.END_DOCUMENT) { - if (type != TypedXmlPullParser.START_TAG) { - continue; - } - - String tag = parser.getName(); - if (tag.equals(TAG_DEVICE_OWNER)) { - String name = parser.getAttributeValue(null, ATTR_NAME); - String packageName = parser.getAttributeValue(null, ATTR_PACKAGE); - mDeviceOwner = new OwnerInfo(name, packageName, - /* userRestrictionsMigrated =*/ false, /* remoteBugreportUri =*/ null, - /* remoteBugreportHash =*/ null, /* isOrganizationOwnedDevice =*/ true); - mDeviceOwnerUserId = UserHandle.USER_SYSTEM; - } else if (tag.equals(TAG_DEVICE_INITIALIZER)) { - // Deprecated tag - } else if (tag.equals(TAG_PROFILE_OWNER)) { - String profileOwnerPackageName = parser.getAttributeValue(null, ATTR_PACKAGE); - String profileOwnerName = parser.getAttributeValue(null, ATTR_NAME); - String profileOwnerComponentStr = - parser.getAttributeValue(null, ATTR_COMPONENT_NAME); - int userId = parser.getAttributeInt(null, ATTR_USERID); - OwnerInfo profileOwnerInfo = null; - if (profileOwnerComponentStr != null) { - ComponentName admin = ComponentName.unflattenFromString( - profileOwnerComponentStr); - if (admin != null) { - profileOwnerInfo = new OwnerInfo(profileOwnerName, admin, - /* userRestrictionsMigrated =*/ false, null, - null, /* isOrganizationOwnedDevice =*/ false); - } else { - // This shouldn't happen but switch from package name -> component name - // might have written bad device owner files. b/17652534 - Slog.e(TAG, "Error parsing device-owner file. Bad component name " + - profileOwnerComponentStr); - } - } - if (profileOwnerInfo == null) { - profileOwnerInfo = new OwnerInfo(profileOwnerName, profileOwnerPackageName, - /* userRestrictionsMigrated =*/ false, - /* remoteBugreportUri =*/ null, /* remoteBugreportHash =*/ - null, /* isOrganizationOwnedDevice =*/ false); - } - mProfileOwners.put(userId, profileOwnerInfo); - } else if (TAG_SYSTEM_UPDATE_POLICY.equals(tag)) { - mSystemUpdatePolicy = SystemUpdatePolicy.restoreFromXml(parser); - } else { - throw new XmlPullParserException( - "Unexpected tag in device owner file: " + tag); - } - } - input.close(); - } catch (XmlPullParserException | IOException e) { - Slog.e(TAG, "Error parsing device-owner file", e); - } - return true; - } - void writeDeviceOwner() { synchronized (mLock) { if (DEBUG) { @@ -1047,9 +901,6 @@ class Owners { mDeviceOwnerUserId); break; } - case TAG_DEVICE_INITIALIZER: - // Deprecated tag - break; case TAG_SYSTEM_UPDATE_POLICY: mSystemUpdatePolicy = SystemUpdatePolicy.restoreFromXml(parser); break; @@ -1087,7 +938,6 @@ class Owners { default: Slog.e(TAG, "Unexpected tag: " + tag); return false; - } return true; } @@ -1136,30 +986,16 @@ class Owners { public final String name; public final String packageName; public final ComponentName admin; - public boolean userRestrictionsMigrated; public String remoteBugreportUri; public String remoteBugreportHash; public boolean isOrganizationOwnedDevice; - public OwnerInfo(String name, String packageName, boolean userRestrictionsMigrated, - String remoteBugreportUri, String remoteBugreportHash, - boolean isOrganizationOwnedDevice) { - this.name = name; - this.packageName = packageName; - this.admin = new ComponentName(packageName, ""); - this.userRestrictionsMigrated = userRestrictionsMigrated; - this.remoteBugreportUri = remoteBugreportUri; - this.remoteBugreportHash = remoteBugreportHash; - this.isOrganizationOwnedDevice = isOrganizationOwnedDevice; - } - - public OwnerInfo(String name, ComponentName admin, boolean userRestrictionsMigrated, + OwnerInfo(String name, ComponentName admin, String remoteBugreportUri, String remoteBugreportHash, boolean isOrganizationOwnedDevice) { this.name = name; this.admin = admin; this.packageName = admin.getPackageName(); - this.userRestrictionsMigrated = userRestrictionsMigrated; this.remoteBugreportUri = remoteBugreportUri; this.remoteBugreportHash = remoteBugreportHash; this.isOrganizationOwnedDevice = isOrganizationOwnedDevice; @@ -1167,14 +1003,12 @@ class Owners { public void writeToXml(TypedXmlSerializer out, String tag) throws IOException { out.startTag(null, tag); - out.attribute(null, ATTR_PACKAGE, packageName); if (name != null) { out.attribute(null, ATTR_NAME, name); } if (admin != null) { out.attribute(null, ATTR_COMPONENT_NAME, admin.flattenToString()); } - out.attributeBoolean(null, ATTR_USER_RESTRICTIONS_MIGRATED, userRestrictionsMigrated); if (remoteBugreportUri != null) { out.attribute(null, ATTR_REMOTE_BUGREPORT_URI, remoteBugreportUri); } @@ -1189,14 +1023,9 @@ class Owners { } public static OwnerInfo readFromXml(TypedXmlPullParser parser) { - final String packageName = parser.getAttributeValue(null, ATTR_PACKAGE); final String name = parser.getAttributeValue(null, ATTR_NAME); final String componentName = parser.getAttributeValue(null, ATTR_COMPONENT_NAME); - final String userRestrictionsMigratedStr = - parser.getAttributeValue(null, ATTR_USER_RESTRICTIONS_MIGRATED); - final boolean userRestrictionsMigrated = - ("true".equals(userRestrictionsMigratedStr)); final String remoteBugreportUri = parser.getAttributeValue(null, ATTR_REMOTE_BUGREPORT_URI); final String remoteBugreportHash = parser.getAttributeValue(null, @@ -1210,23 +1039,18 @@ class Owners { final boolean isOrgOwnedDevice = ("true".equals(isOrgOwnedDeviceStr)) | canAccessDeviceIds; - // Has component name? If so, return [name, component] - if (componentName != null) { - final ComponentName admin = ComponentName.unflattenFromString(componentName); - if (admin != null) { - return new OwnerInfo(name, admin, userRestrictionsMigrated, - remoteBugreportUri, remoteBugreportHash, isOrgOwnedDevice); - } else { - // This shouldn't happen but switch from package name -> component name - // might have written bad device owner files. b/17652534 - Slog.e(TAG, "Error parsing owner file. Bad component name " + - componentName); - } + if (componentName == null) { + Slog.e(TAG, "Owner component not found"); + return null; + } + final ComponentName admin = ComponentName.unflattenFromString(componentName); + if (admin == null) { + Slog.e(TAG, "Owner component not parsable: " + componentName); + return null; } - // Else, build with [name, package] - return new OwnerInfo(name, packageName, userRestrictionsMigrated, remoteBugreportUri, - remoteBugreportHash, isOrgOwnedDevice); + return new OwnerInfo( + name, admin, remoteBugreportUri, remoteBugreportHash, isOrgOwnedDevice); } public void dump(IndentingPrintWriter pw) { @@ -1284,11 +1108,6 @@ class Owners { } @VisibleForTesting - File getLegacyConfigFile() { - return new File(mInjector.environmentGetDataSystemDirectory(), DEVICE_OWNER_XML_LEGACY); - } - - @VisibleForTesting File getDeviceOwnerFile() { return new File(mInjector.environmentGetDataSystemDirectory(), DEVICE_OWNER_XML); } diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java index c0b4f0fe5812..ac542935fa0a 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java @@ -585,6 +585,7 @@ public final class BackgroundRestrictionTest { DeviceConfigSession<Float> bgCurrentDrainRestrictedBucketThreshold = null; DeviceConfigSession<Float> bgCurrentDrainBgRestrictedThreshold = null; DeviceConfigSession<Boolean> bgPromptFgsWithNotiToBgRestricted = null; + DeviceConfigSession<Boolean> bgPromptAbusiveAppToBgRestricted = null; DeviceConfigSession<Long> bgNotificationMinInterval = null; DeviceConfigSession<Integer> bgBatteryExemptionTypes = null; DeviceConfigSession<Boolean> bgCurrentDrainDecoupleThresholds = null; @@ -642,6 +643,14 @@ public final class BackgroundRestrictionTest { R.bool.config_bg_prompt_fgs_with_noti_to_bg_restricted)); bgPromptFgsWithNotiToBgRestricted.set(true); + bgPromptAbusiveAppToBgRestricted = new DeviceConfigSession<>( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + ConstantsObserver.KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED, + DeviceConfig::getBoolean, + mContext.getResources().getBoolean( + R.bool.config_bg_prompt_abusive_apps_to_bg_restricted)); + bgPromptAbusiveAppToBgRestricted.set(true); + bgNotificationMinInterval = new DeviceConfigSession<>( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, ConstantsObserver.KEY_BG_ABUSIVE_NOTIFICATION_MINIMAL_INTERVAL, @@ -1055,6 +1064,7 @@ public final class BackgroundRestrictionTest { closeIfNotNull(bgCurrentDrainRestrictedBucketThreshold); closeIfNotNull(bgCurrentDrainBgRestrictedThreshold); closeIfNotNull(bgPromptFgsWithNotiToBgRestricted); + closeIfNotNull(bgPromptAbusiveAppToBgRestricted); closeIfNotNull(bgNotificationMinInterval); closeIfNotNull(bgBatteryExemptionTypes); closeIfNotNull(bgCurrentDrainDecoupleThresholds); @@ -1613,6 +1623,7 @@ public final class BackgroundRestrictionTest { DeviceConfigSession<String> bgPermissionsInMonitor = null; DeviceConfigSession<Boolean> bgCurrentDrainHighThresholdByBgLocation = null; DeviceConfigSession<Boolean> bgCurrentDrainDecoupleThresholds = null; + DeviceConfigSession<Boolean> bgPromptAbusiveAppToBgRestricted = null; mBgRestrictionController.addAppBackgroundRestrictionListener(listener); @@ -1751,6 +1762,14 @@ public final class BackgroundRestrictionTest { AppBatteryPolicy.DEFAULT_BG_CURRENT_DRAIN_DECOUPLE_THRESHOLD); bgCurrentDrainDecoupleThresholds.set(true); + bgPromptAbusiveAppToBgRestricted = new DeviceConfigSession<>( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + ConstantsObserver.KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED, + DeviceConfig::getBoolean, + mContext.getResources().getBoolean( + R.bool.config_bg_prompt_abusive_apps_to_bg_restricted)); + bgPromptAbusiveAppToBgRestricted.set(true); + mCurrentTimeMillis = 10_000L; doReturn(mCurrentTimeMillis - windowMs).when(stats).getStatsStartTimestamp(); doReturn(mCurrentTimeMillis).when(stats).getStatsEndTimestamp(); @@ -2168,6 +2187,7 @@ public final class BackgroundRestrictionTest { closeIfNotNull(bgBatteryExemptionTypes); closeIfNotNull(bgPermissionMonitorEnabled); closeIfNotNull(bgPermissionsInMonitor); + closeIfNotNull(bgPromptAbusiveAppToBgRestricted); closeIfNotNull(bgCurrentDrainHighThresholdByBgLocation); closeIfNotNull(bgCurrentDrainDecoupleThresholds); } diff --git a/services/tests/mockingservicestests/src/com/android/server/companion/virtual/CameraAccessControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/companion/virtual/CameraAccessControllerTest.java index 1b9cb28dc8b2..c4c3abc1388e 100644 --- a/services/tests/mockingservicestests/src/com/android/server/companion/virtual/CameraAccessControllerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/companion/virtual/CameraAccessControllerTest.java @@ -24,6 +24,7 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -34,6 +35,7 @@ import android.hardware.camera2.CameraInjectionSession; import android.hardware.camera2.CameraManager; import android.os.Process; import android.testing.TestableContext; +import android.util.ArraySet; import androidx.test.InstrumentationRegistry; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -73,11 +75,11 @@ public class CameraAccessControllerTest { private ApplicationInfo mTestAppInfo = new ApplicationInfo(); private ApplicationInfo mOtherAppInfo = new ApplicationInfo(); + private ArraySet<Integer> mRunningUids = new ArraySet<>(); @Captor ArgumentCaptor<CameraInjectionSession.InjectionStatusCallback> mInjectionCallbackCaptor; - @Before public void setUp() throws PackageManager.NameNotFoundException { MockitoAnnotations.initMocks(this); @@ -89,6 +91,7 @@ public class CameraAccessControllerTest { mBlockedCallback); mTestAppInfo.uid = Process.FIRST_APPLICATION_UID; mOtherAppInfo.uid = Process.FIRST_APPLICATION_UID + 1; + mRunningUids.add(Process.FIRST_APPLICATION_UID); when(mPackageManager.getApplicationInfo(eq(TEST_APP_PACKAGE), anyInt())).thenReturn( mTestAppInfo); when(mPackageManager.getApplicationInfo(eq(OTHER_APP_PACKAGE), anyInt())).thenReturn( @@ -104,7 +107,6 @@ public class CameraAccessControllerTest { verify(mCameraManager, never()).injectCamera(any(), any(), any(), any(), any()); } - @Test public void onCameraOpened_uidRunning_cameraBlocked() throws CameraAccessException { when(mDeviceManagerInternal.isAppRunningOnAnyVirtualDevice( @@ -128,7 +130,6 @@ public class CameraAccessControllerTest { verify(session).close(); } - @Test public void onCameraClosed_otherCameraClosed_cameraNotUnblocked() throws CameraAccessException { when(mDeviceManagerInternal.isAppRunningOnAnyVirtualDevice( @@ -197,4 +198,33 @@ public class CameraAccessControllerTest { mInjectionCallbackCaptor.getValue().onInjectionError(ERROR_INJECTION_UNSUPPORTED); verify(mBlockedCallback).onCameraAccessBlocked(eq(mTestAppInfo.uid)); } + + @Test + public void twoCameraAccessesBySameUid_secondOnVirtualDisplay_noCallbackButCameraCanBlocked() + throws CameraAccessException { + when(mDeviceManagerInternal.isAppRunningOnAnyVirtualDevice( + eq(mTestAppInfo.uid))).thenReturn(false); + mController.onCameraOpened(FRONT_CAMERA, TEST_APP_PACKAGE); + mController.blockCameraAccessIfNeeded(mRunningUids); + + verify(mCameraManager).injectCamera(eq(TEST_APP_PACKAGE), eq(FRONT_CAMERA), anyString(), + any(), mInjectionCallbackCaptor.capture()); + CameraInjectionSession session = mock(CameraInjectionSession.class); + mInjectionCallbackCaptor.getValue().onInjectionSucceeded(session); + mInjectionCallbackCaptor.getValue().onInjectionError(ERROR_INJECTION_UNSUPPORTED); + verify(mBlockedCallback).onCameraAccessBlocked(eq(mTestAppInfo.uid)); + } + + @Test + public void twoCameraAccessesBySameUid_secondOnVirtualDisplay_firstCloseThenOpenCameraUnblock() + throws CameraAccessException { + when(mDeviceManagerInternal.isAppRunningOnAnyVirtualDevice( + eq(mTestAppInfo.uid))).thenReturn(false); + mController.onCameraOpened(FRONT_CAMERA, TEST_APP_PACKAGE); + mController.blockCameraAccessIfNeeded(mRunningUids); + mController.onCameraClosed(FRONT_CAMERA); + mController.onCameraOpened(FRONT_CAMERA, TEST_APP_PACKAGE); + + verify(mCameraManager, times(1)).injectCamera(any(), any(), any(), any(), any()); + } } diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java index 6a27ecc7f094..1753fc7a61e4 100644 --- a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java @@ -737,6 +737,101 @@ public class JobSchedulerServiceTest { assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed()); } + @Test + public void testGetRescheduleJobForPeriodic_outsideWindow_flex_failedJob_longPeriod() { + JobStatus job = createJobStatus( + "testGetRescheduleJobForPeriodic_outsideWindow_flex_failedJob_longPeriod", + createJobInfo().setPeriodic(7 * DAY_IN_MILLIS, 9 * HOUR_IN_MILLIS)); + JobStatus failedJob = mService.getRescheduleJobForFailureLocked(job); + // First window starts 6.625 days from now. + advanceElapsedClock(6 * DAY_IN_MILLIS + 15 * HOUR_IN_MILLIS); + long now = sElapsedRealtimeClock.millis(); + long nextWindowStartTime = now + 7 * DAY_IN_MILLIS; + long nextWindowEndTime = nextWindowStartTime + 9 * HOUR_IN_MILLIS; + + advanceElapsedClock(6 * HOUR_IN_MILLIS + MINUTE_IN_MILLIS); + // Say the job ran at the very end of its previous window. The intended JSS behavior is to + // have consistent windows, so the new window should start as soon as the previous window + // ended and end PERIOD time after the previous window ended. + JobStatus rescheduledJob = mService.getRescheduleJobForPeriodic(failedJob); + assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime()); + assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed()); + + advanceElapsedClock(DAY_IN_MILLIS); + // Say the job ran a day late. Since the period is massive compared to the flex, JSS should + // put the rescheduled job in the original window. + rescheduledJob = mService.getRescheduleJobForPeriodic(failedJob); + assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime()); + assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed()); + + // 1 day before the start of the next window. Given the large period, respect the original + // next window. + advanceElapsedClock(nextWindowStartTime - sElapsedRealtimeClock.millis() - DAY_IN_MILLIS); + rescheduledJob = mService.getRescheduleJobForPeriodic(job); + assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime()); + assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed()); + + // 1 hour before the start of the next window. It's too close to the next window, so the + // returned job should be for the window after. + long oneHourBeforeNextWindow = + nextWindowStartTime - sElapsedRealtimeClock.millis() - HOUR_IN_MILLIS; + long fiveMinsBeforeNextWindow = + nextWindowStartTime - sElapsedRealtimeClock.millis() - 5 * MINUTE_IN_MILLIS; + advanceElapsedClock(oneHourBeforeNextWindow); + nextWindowStartTime += 7 * DAY_IN_MILLIS; + nextWindowEndTime += 7 * DAY_IN_MILLIS; + rescheduledJob = mService.getRescheduleJobForPeriodic(job); + assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime()); + assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed()); + + // 5 minutes before the start of the next window. It's too close to the next window, so the + // returned job should be for the window after. + advanceElapsedClock(fiveMinsBeforeNextWindow); + rescheduledJob = mService.getRescheduleJobForPeriodic(job); + assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime()); + assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed()); + + advanceElapsedClock(14 * DAY_IN_MILLIS); + // Say that the job ran at this point, probably because the phone was off the entire time. + // The next window should be consistent (start and end at the time it would have had the job + // run normally in previous windows). + nextWindowStartTime += 14 * DAY_IN_MILLIS; + nextWindowEndTime += 14 * DAY_IN_MILLIS; + + rescheduledJob = mService.getRescheduleJobForPeriodic(failedJob); + assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime()); + assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed()); + + // Test original job again but with a huge delay from the original execution window + + // 1 day before the start of the next window. Given the large period, respect the original + // next window. + advanceElapsedClock(nextWindowStartTime - sElapsedRealtimeClock.millis() - DAY_IN_MILLIS); + rescheduledJob = mService.getRescheduleJobForPeriodic(job); + assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime()); + assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed()); + + // 1 hour before the start of the next window. It's too close to the next window, so the + // returned job should be for the window after. + oneHourBeforeNextWindow = + nextWindowStartTime - sElapsedRealtimeClock.millis() - HOUR_IN_MILLIS; + fiveMinsBeforeNextWindow = + nextWindowStartTime - sElapsedRealtimeClock.millis() - 5 * MINUTE_IN_MILLIS; + advanceElapsedClock(oneHourBeforeNextWindow); + nextWindowStartTime += 7 * DAY_IN_MILLIS; + nextWindowEndTime += 7 * DAY_IN_MILLIS; + rescheduledJob = mService.getRescheduleJobForPeriodic(job); + assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime()); + assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed()); + + // 5 minutes before the start of the next window. It's too close to the next window, so the + // returned job should be for the window after. + advanceElapsedClock(fiveMinsBeforeNextWindow); + rescheduledJob = mService.getRescheduleJobForPeriodic(job); + assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime()); + assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed()); + } + /** Tests that rare job batching works as expected. */ @Test public void testRareJobBatching() { diff --git a/services/tests/mockingservicestests/src/com/android/server/power/PowerManagerServiceMockingTest.java b/services/tests/mockingservicestests/src/com/android/server/power/PowerManagerServiceMockingTest.java index 9cf6c0325024..5c4657fb0027 100644 --- a/services/tests/mockingservicestests/src/com/android/server/power/PowerManagerServiceMockingTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/power/PowerManagerServiceMockingTest.java @@ -67,6 +67,8 @@ import com.android.server.power.batterysaver.BatterySaverStateMachine; import com.android.server.power.batterysaver.BatterySavingStats; import com.android.server.testutils.OffsettableClock; +import java.util.concurrent.Executor; + import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -164,7 +166,8 @@ public class PowerManagerServiceMockingTest { @Override Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats, SuspendBlocker suspendBlocker, WindowManagerPolicy policy, - FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector) { + FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector, + Executor executor) { return mNotifierMock; } diff --git a/services/tests/servicestests/assets/OwnersTest/device_owner_1.xml b/services/tests/servicestests/assets/OwnersTest/device_owner_1.xml new file mode 100644 index 000000000000..d150b293fb08 --- /dev/null +++ b/services/tests/servicestests/assets/OwnersTest/device_owner_1.xml @@ -0,0 +1,6 @@ +<?xml version='1.0' encoding='UTF-8' standalone='yes' ?> +<root> + <device-owner package="com.afwsamples.testdpc" name="" component="com.afwsamples.testdpc/com.afwsamples.testdpc.DeviceAdminReceiver" isPoOrganizationOwnedDevice="true" /> + <device-owner-context userId="0" /> + <system-update-policy policy_type="2" install_window_start="0" install_window_end="540" /> +</root>
\ No newline at end of file diff --git a/services/tests/servicestests/assets/OwnersTest/profile_owner_1.xml b/services/tests/servicestests/assets/OwnersTest/profile_owner_1.xml new file mode 100644 index 000000000000..1f78b711ddab --- /dev/null +++ b/services/tests/servicestests/assets/OwnersTest/profile_owner_1.xml @@ -0,0 +1,4 @@ +<?xml version='1.0' encoding='UTF-8' standalone='yes' ?> +<root> + <profile-owner package="com.afwsamples.testdpc" name="com.afwsamples.testdpc" component="com.afwsamples.testdpc/com.afwsamples.testdpc.DeviceAdminReceiver" /> +</root>
\ No newline at end of file diff --git a/services/tests/servicestests/assets/OwnersTest/test01/input.xml b/services/tests/servicestests/assets/OwnersTest/test01/input.xml deleted file mode 100644 index db3e974f5d07..000000000000 --- a/services/tests/servicestests/assets/OwnersTest/test01/input.xml +++ /dev/null @@ -1 +0,0 @@ -<?xml version='1.0' encoding='utf-8' standalone='yes' ?> diff --git a/services/tests/servicestests/assets/OwnersTest/test02/input.xml b/services/tests/servicestests/assets/OwnersTest/test02/input.xml deleted file mode 100644 index 321842b27452..000000000000 --- a/services/tests/servicestests/assets/OwnersTest/test02/input.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version='1.0' encoding='utf-8' standalone='yes' ?> -<device-owner package="com.google.android.testdpc" /> diff --git a/services/tests/servicestests/assets/OwnersTest/test03/input.xml b/services/tests/servicestests/assets/OwnersTest/test03/input.xml deleted file mode 100644 index 1bbfdadf6ebb..000000000000 --- a/services/tests/servicestests/assets/OwnersTest/test03/input.xml +++ /dev/null @@ -1,3 +0,0 @@ -<?xml version='1.0' encoding='utf-8' standalone='yes' ?> -<profile-owner package="com.google.android.testdpc0" name="0" userId="10" component="com.google.android.testdpc/com.google.android.testdpc.DeviceAdminReceiver0" /> -<profile-owner package="com.google.android.testdpc1" name="1" userId="11" /> diff --git a/services/tests/servicestests/assets/OwnersTest/test04/input.xml b/services/tests/servicestests/assets/OwnersTest/test04/input.xml deleted file mode 100644 index 8be51d9a45e9..000000000000 --- a/services/tests/servicestests/assets/OwnersTest/test04/input.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version='1.0' encoding='utf-8' standalone='yes' ?> -<device-owner package="com.google.android.testdpc" /> -<profile-owner package="com.google.android.testdpc0" name="0" userId="10" component="com.google.android.testdpc/com.google.android.testdpc.DeviceAdminReceiver0" /> -<profile-owner package="com.google.android.testdpc1" name="1" userId="11" /> -<device-initializer package="com.google.android.testdpcx" name="di" component="com.google.android.testdpcx/receiver" /> -<system-update-policy policy_type="5" /> diff --git a/services/tests/servicestests/assets/OwnersTest/test05/input.xml b/services/tests/servicestests/assets/OwnersTest/test05/input.xml deleted file mode 100644 index dbcb8588654e..000000000000 --- a/services/tests/servicestests/assets/OwnersTest/test05/input.xml +++ /dev/null @@ -1,3 +0,0 @@ -<?xml version='1.0' encoding='utf-8' standalone='yes' ?> -<device-initializer package="com.google.android.testdpcx" name="di" component="com.google.android.testdpcx/receiver" /> - diff --git a/services/tests/servicestests/assets/OwnersTest/test06/input.xml b/services/tests/servicestests/assets/OwnersTest/test06/input.xml deleted file mode 100644 index 794622b0b995..000000000000 --- a/services/tests/servicestests/assets/OwnersTest/test06/input.xml +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version='1.0' encoding='utf-8' standalone='yes' ?> -<system-update-policy policy_type="5" /> diff --git a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java index 3d3c1abb3e91..4e059b4b7432 100644 --- a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java @@ -16,6 +16,9 @@ package com.android.server; +import static com.android.server.GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; +import static com.android.server.GestureLauncherService.EMERGENCY_GESTURE_TAP_DETECTION_MIN_TIME_MS; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -248,7 +251,7 @@ public class GestureLauncherServiceTest { mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); long eventTime = INITIAL_EVENT_TIME_MILLIS + - GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; + CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); boolean interactive = true; @@ -296,7 +299,7 @@ public class GestureLauncherServiceTest { assertFalse(intercepted); assertFalse(outLaunched.value); - final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; + final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; eventTime += interval; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); @@ -341,7 +344,7 @@ public class GestureLauncherServiceTest { assertFalse(intercepted); assertFalse(outLaunched.value); - final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; + final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; eventTime += interval; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); @@ -435,7 +438,7 @@ public class GestureLauncherServiceTest { assertFalse(intercepted); assertFalse(outLaunched.value); - final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; + final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; eventTime += interval; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); @@ -489,7 +492,7 @@ public class GestureLauncherServiceTest { assertFalse(intercepted); assertFalse(outLaunched.value); - final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; + final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; // 2nd button triggers camera eventTime += interval; @@ -578,7 +581,7 @@ public class GestureLauncherServiceTest { assertFalse(intercepted); assertFalse(outLaunched.value); - final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; + final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; // 3 more button presses which should not trigger any gesture (camera gesture disabled) for (int i = 0; i < 3; i++) { eventTime += interval; @@ -632,7 +635,7 @@ public class GestureLauncherServiceTest { assertFalse(intercepted); assertFalse(outLaunched.value); - final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; + final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; // 3 more button presses which should not trigger any gesture, but intercepts action. for (int i = 0; i < 3; i++) { eventTime += interval; @@ -735,7 +738,7 @@ public class GestureLauncherServiceTest { interactive, outLaunched); assertTrue(intercepted); assertFalse(outLaunched.value); - interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; + interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; eventTime += interval; } } @@ -763,12 +766,33 @@ public class GestureLauncherServiceTest { interactive, outLaunched); assertTrue(intercepted); assertFalse(outLaunched.value); - interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; + interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; eventTime += interval; } } @Test + public void testInterceptPowerKeyDown_triggerEmergency_fiveFastTaps_gestureIgnored() { + // Trigger emergency by tapping button 5 times + long eventTime = triggerEmergencyGesture(/* tapIntervalMs= */ 1); + + // Add 1 more millisecond and send the event again. + eventTime += 1; + + // Subsequent long press is intercepted, but should not trigger any gesture + KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, + IGNORED_REPEAT, IGNORED_META_STATE, IGNORED_DEVICE_ID, IGNORED_SCANCODE, + KeyEvent.FLAG_LONG_PRESS); + MutableBoolean outLaunched = new MutableBoolean(true); + boolean intercepted = mGestureLauncherService.interceptPowerKeyDown( + keyEvent, + /* interactive= */ true, + outLaunched); + assertFalse(intercepted); + assertFalse(outLaunched.value); + } + + @Test public void testInterceptPowerKeyDown_triggerEmergency_longPress_cooldownTriggered() { // Enable power button cooldown withEmergencyGesturePowerButtonCooldownPeriodMsValue(3000); @@ -890,7 +914,7 @@ public class GestureLauncherServiceTest { assertFalse(intercepted); assertFalse(outLaunched.value); - final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; + final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; eventTime += interval; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT, IGNORED_META_STATE, IGNORED_DEVICE_ID, IGNORED_SCANCODE, @@ -936,7 +960,7 @@ public class GestureLauncherServiceTest { assertFalse(intercepted); assertFalse(outLaunched.value); - final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; + final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; eventTime += interval; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); @@ -983,7 +1007,7 @@ public class GestureLauncherServiceTest { assertFalse(intercepted); assertFalse(outLaunched.value); - final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; + final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; eventTime += interval; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); @@ -1075,7 +1099,7 @@ public class GestureLauncherServiceTest { assertFalse(intercepted); assertFalse(outLaunched.value); - final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; + final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; eventTime += interval; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); @@ -1120,7 +1144,7 @@ public class GestureLauncherServiceTest { assertFalse(intercepted); assertFalse(outLaunched.value); - final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; + final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; eventTime += interval; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); @@ -1212,7 +1236,7 @@ public class GestureLauncherServiceTest { assertFalse(intercepted); assertFalse(outLaunched.value); - final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; + final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; eventTime += interval; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); @@ -1261,7 +1285,7 @@ public class GestureLauncherServiceTest { assertFalse(intercepted); assertFalse(outLaunched.value); - final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; + final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; eventTime += interval; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); @@ -1306,7 +1330,7 @@ public class GestureLauncherServiceTest { assertFalse(intercepted); assertFalse(outLaunched.value); - final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; + final long interval = CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS; eventTime += interval; keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); @@ -1384,9 +1408,20 @@ public class GestureLauncherServiceTest { /** * Helper method to trigger emergency gesture by pressing button for 5 times. + * * @return last event time. */ private long triggerEmergencyGesture() { + return triggerEmergencyGesture(CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1); + } + + /** + * Helper method to trigger emergency gesture by pressing button for 5 times with + * specified interval between each tap + * + * @return last event time. + */ + private long triggerEmergencyGesture(long tapIntervalMs) { // Enable emergency power gesture withEmergencyGestureEnabledConfigValue(true); withEmergencyGestureEnabledSettingValue(true); @@ -1402,8 +1437,7 @@ public class GestureLauncherServiceTest { keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT); mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); - final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; - eventTime += interval; + eventTime += tapIntervalMs; } // 5th button press should trigger the emergency flow @@ -1412,12 +1446,22 @@ public class GestureLauncherServiceTest { outLaunched.value = false; boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); - assertTrue(outLaunched.value); + long emergencyGestureTapDetectionMinTimeMs = Settings.Global.getInt( + mContext.getContentResolver(), + Settings.Global.EMERGENCY_GESTURE_TAP_DETECTION_MIN_TIME_MS, + EMERGENCY_GESTURE_TAP_DETECTION_MIN_TIME_MS); assertTrue(intercepted); - verify(mUiEventLogger, times(1)) - .log(GestureLauncherService.GestureLauncherEvent.GESTURE_EMERGENCY_TAP_POWER); - verify(mStatusBarManagerInternal).onEmergencyActionLaunchGestureDetected(); - + if (tapIntervalMs * 4 > emergencyGestureTapDetectionMinTimeMs) { + assertTrue(outLaunched.value); + verify(mUiEventLogger, times(1)) + .log(GestureLauncherService.GestureLauncherEvent.GESTURE_EMERGENCY_TAP_POWER); + verify(mStatusBarManagerInternal).onEmergencyActionLaunchGestureDetected(); + } else { + assertFalse(outLaunched.value); + verify(mUiEventLogger, never()) + .log(GestureLauncherService.GestureLauncherEvent.GESTURE_EMERGENCY_TAP_POWER); + verify(mStatusBarManagerInternal, never()).onEmergencyActionLaunchGestureDetected(); + } return eventTime; } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java index 97ebdd4ad7fa..08df4381ad62 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java @@ -58,6 +58,7 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -435,7 +436,7 @@ public class AbstractAccessibilityServiceConnectionTest { VIEWID_RESOURCE_NAME, INTERACTION_ID, mMockCallback, TID); verify(mMockIA11yInteractionConnection).findAccessibilityNodeInfosByViewId( eq(ROOT_NODE_ID), eq(VIEWID_RESOURCE_NAME), any(), eq(INTERACTION_ID), - captor.capture(), anyInt(), eq(PID), eq(TID), any()); + captor.capture(), anyInt(), eq(PID), eq(TID), any(), nullable(float[].class)); verify(mMockSecurityPolicy).computeValidReportedPackages(any(), anyInt()); verifyReplaceActions(captor.getValue()); } @@ -449,7 +450,7 @@ public class AbstractAccessibilityServiceConnectionTest { VIEW_TEXT, INTERACTION_ID, mMockCallback, TID); verify(mMockIA11yInteractionConnection).findAccessibilityNodeInfosByText( eq(ROOT_NODE_ID), eq(VIEW_TEXT), any(), eq(INTERACTION_ID), - captor.capture(), anyInt(), eq(PID), eq(TID), any()); + captor.capture(), anyInt(), eq(PID), eq(TID), any(), nullable(float[].class)); verify(mMockSecurityPolicy).computeValidReportedPackages(any(), anyInt()); verifyReplaceActions(captor.getValue()); } @@ -463,7 +464,7 @@ public class AbstractAccessibilityServiceConnectionTest { INTERACTION_ID, mMockCallback, 0, TID, null); verify(mMockIA11yInteractionConnection).findAccessibilityNodeInfoByAccessibilityId( eq(ROOT_NODE_ID), any(), eq(INTERACTION_ID), captor.capture(), anyInt(), - eq(PID), eq(TID), any(), any()); + eq(PID), eq(TID), any(), nullable(float[].class), any()); verify(mMockSecurityPolicy).computeValidReportedPackages(any(), anyInt()); verifyReplaceActions(captor.getValue()); } @@ -476,7 +477,8 @@ public class AbstractAccessibilityServiceConnectionTest { mServiceConnection.findFocus(PIP_WINDOWID, ROOT_NODE_ID, FOCUS_INPUT, INTERACTION_ID, mMockCallback, TID); verify(mMockIA11yInteractionConnection).findFocus(eq(ROOT_NODE_ID), eq(FOCUS_INPUT), - any(), eq(INTERACTION_ID), captor.capture(), anyInt(), eq(PID), eq(TID), any()); + any(), eq(INTERACTION_ID), captor.capture(), anyInt(), eq(PID), eq(TID), any(), + nullable(float[].class)); verify(mMockSecurityPolicy).computeValidReportedPackages(any(), anyInt()); verifyReplaceActions(captor.getValue()); } @@ -489,7 +491,8 @@ public class AbstractAccessibilityServiceConnectionTest { mServiceConnection.focusSearch(PIP_WINDOWID, ROOT_NODE_ID, FOCUS_DOWN, INTERACTION_ID, mMockCallback, TID); verify(mMockIA11yInteractionConnection).focusSearch(eq(ROOT_NODE_ID), eq(FOCUS_DOWN), - any(), eq(INTERACTION_ID), captor.capture(), anyInt(), eq(PID), eq(TID), any()); + any(), eq(INTERACTION_ID), captor.capture(), anyInt(), eq(PID), eq(TID), any(), + nullable(float[].class)); verify(mMockSecurityPolicy).computeValidReportedPackages(any(), anyInt()); verifyReplaceActions(captor.getValue()); } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInteractionControllerNodeRequestsTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInteractionControllerNodeRequestsTest.java index 022c137491df..842b23c91e41 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInteractionControllerNodeRequestsTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInteractionControllerNodeRequestsTest.java @@ -842,7 +842,7 @@ public class AccessibilityInteractionControllerNodeRequestsTest { null, interactionId, callback, prefetchFlags, processAndThreadId, - processAndThreadId, null, null); + processAndThreadId, null, null, null); } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/ActionReplacingCallbackTest.java b/services/tests/servicestests/src/com/android/server/accessibility/ActionReplacingCallbackTest.java index 72820f15315e..c16f3d3fa1ab 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/ActionReplacingCallbackTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/ActionReplacingCallbackTest.java @@ -16,6 +16,27 @@ package com.android.server.accessibility; +import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS; +import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS; +import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK; +import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_COLLAPSE; +import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_CONTEXT_CLICK; +import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND; + +import static junit.framework.TestCase.assertTrue; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertThat; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyObject; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.MockitoAnnotations.initMocks; + import android.graphics.Region; import android.os.RemoteException; import android.view.MagnificationSpec; @@ -35,28 +56,8 @@ import org.mockito.Captor; import org.mockito.Mock; import java.util.Arrays; -import java.util.HashSet; import java.util.List; -import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS; -import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS; -import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK; -import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_COLLAPSE; -import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND; -import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_CONTEXT_CLICK; -import static junit.framework.TestCase.assertTrue; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.MockitoAnnotations.initMocks; - /** * Tests for ActionReplacingCallback */ @@ -130,8 +131,8 @@ public class ActionReplacingCallbackTest { verify(mMockReplacerConnection).findAccessibilityNodeInfoByAccessibilityId( eq(AccessibilityNodeInfo.ROOT_NODE_ID), (Region) anyObject(), mInteractionIdCaptor.capture(), eq(mActionReplacingCallback), eq(0), - eq(INTERROGATING_PID), eq(INTERROGATING_TID), (MagnificationSpec) anyObject(), - eq(null)); + eq(INTERROGATING_PID), eq(INTERROGATING_TID), nullable(MagnificationSpec.class), + nullable(float[].class), eq(null)); mReplacerInteractionId = mInteractionIdCaptor.getValue().intValue(); } @@ -247,7 +248,7 @@ public class ActionReplacingCallbackTest { .findAccessibilityNodeInfoByAccessibilityId(eq(AccessibilityNodeInfo.ROOT_NODE_ID), (Region) anyObject(), anyInt(), (ActionReplacingCallback) anyObject(), eq(0), eq(INTERROGATING_PID), eq(INTERROGATING_TID), - (MagnificationSpec) anyObject(), eq(null)); + (MagnificationSpec) anyObject(), nullable(float[].class), eq(null)); ActionReplacingCallback actionReplacingCallback = new ActionReplacingCallback( mMockServiceCallback, mMockReplacerConnection, INTERACTION_ID, INTERROGATING_PID, INTERROGATING_TID); diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java index ca22f80a7189..eac86715e4c7 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java @@ -198,6 +198,31 @@ public class MagnificationControllerTest { } @Test + public void transitionToWindowModeFailedByReset_fullScreenMagnifying_notifyTransitionFailed() + throws RemoteException { + setMagnificationEnabled(MODE_FULLSCREEN); + + mMagnificationController.transitionMagnificationModeLocked(TEST_DISPLAY, + MODE_WINDOW, + mTransitionCallBack); + + verify(mScreenMagnificationController).reset(eq(TEST_DISPLAY), + mCallbackArgumentCaptor.capture()); + // The transition is interrupted and failed by calling reset. + mCallbackArgumentCaptor.getValue().onResult(false); + verify(mTransitionCallBack).onResult(TEST_DISPLAY, false); + final ArgumentCaptor<MagnificationConfig> configCaptor = ArgumentCaptor.forClass( + MagnificationConfig.class); + // The first time is for notifying full-screen enabled and the second time is for notifying + // the target mode transitions failed. + verify(mService, times(2)).notifyMagnificationChanged(eq(TEST_DISPLAY), any(Region.class), + configCaptor.capture()); + final MagnificationConfig actualConfig = configCaptor.getValue(); + assertEquals(MODE_FULLSCREEN, actualConfig.getMode(), 0); + assertEquals(1.0f, actualConfig.getScale(), 0); + } + + @Test public void transitionToWindowMode_disablingWindowMode_enablingWindowWithFormerCenter() throws RemoteException { setMagnificationEnabled(MODE_WINDOW); @@ -479,6 +504,92 @@ public class MagnificationControllerTest { } @Test + public void transitionMagnificationMode_windowEnabled_notifyTargetMagnificationChanged() + throws RemoteException { + setMagnificationEnabled(MODE_WINDOW); + + mMagnificationController.transitionMagnificationModeLocked(TEST_DISPLAY, + MODE_FULLSCREEN, mTransitionCallBack); + mMockConnection.invokeCallbacks(); + + final ArgumentCaptor<MagnificationConfig> configCaptor = ArgumentCaptor.forClass( + MagnificationConfig.class); + // The first time is for notifying window enabled and the second time is for notifying + // the target mode transitions. + verify(mService, times(2)).notifyMagnificationChanged(eq(TEST_DISPLAY), any(Region.class), + configCaptor.capture()); + final MagnificationConfig actualConfig = configCaptor.getValue(); + assertEquals(MODE_FULLSCREEN, actualConfig.getMode(), 0); + } + + @Test + public void transitionConfigMode_windowEnabled_notifyTargetMagnificationChanged() + throws RemoteException { + setMagnificationEnabled(MODE_WINDOW); + + final MagnificationConfig config = obtainMagnificationConfig(MODE_FULLSCREEN); + mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY, + config, true, TEST_SERVICE_ID); + mMockConnection.invokeCallbacks(); + + final ArgumentCaptor<MagnificationConfig> configCaptor = ArgumentCaptor.forClass( + MagnificationConfig.class); + // The first time is for notifying window enabled and the second time is for notifying + // the target mode transitions. + verify(mService, times(2)).notifyMagnificationChanged(eq(TEST_DISPLAY), any(Region.class), + configCaptor.capture()); + final MagnificationConfig actualConfig = configCaptor.getValue(); + assertEquals(config.getCenterX(), actualConfig.getCenterX(), 0); + assertEquals(config.getCenterY(), actualConfig.getCenterY(), 0); + assertEquals(config.getScale(), actualConfig.getScale(), 0); + } + + @Test + public void transitionMagnificationMode_fullScreenEnabled_notifyTargetMagnificationChanged() + throws RemoteException { + setMagnificationEnabled(MODE_FULLSCREEN); + + mMagnificationController.transitionMagnificationModeLocked(TEST_DISPLAY, + MODE_WINDOW, mTransitionCallBack); + verify(mScreenMagnificationController).reset(eq(TEST_DISPLAY), + mCallbackArgumentCaptor.capture()); + mCallbackArgumentCaptor.getValue().onResult(true); + mMockConnection.invokeCallbacks(); + + final ArgumentCaptor<MagnificationConfig> configCaptor = ArgumentCaptor.forClass( + MagnificationConfig.class); + // The first time is for notifying full-screen enabled and the second time is for notifying + // the target mode transitions. + verify(mService, times(2)).notifyMagnificationChanged(eq(TEST_DISPLAY), any(Region.class), + configCaptor.capture()); + final MagnificationConfig actualConfig = configCaptor.getValue(); + assertEquals(MODE_WINDOW, actualConfig.getMode(), 0); + } + + @Test + public void transitionConfigMode_fullScreenEnabled_notifyTargetMagnificationChanged() + throws RemoteException { + setMagnificationEnabled(MODE_FULLSCREEN); + + final MagnificationConfig config = obtainMagnificationConfig(MODE_WINDOW); + mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY, + config, true, TEST_SERVICE_ID); + mMockConnection.invokeCallbacks(); + + final ArgumentCaptor<MagnificationConfig> configCaptor = ArgumentCaptor.forClass( + MagnificationConfig.class); + // The first time is for notifying full-screen enabled and the second time is for notifying + // the target mode transitions. + verify(mService, times(2)).notifyMagnificationChanged(eq(TEST_DISPLAY), any(Region.class), + configCaptor.capture()); + final MagnificationConfig actualConfig = configCaptor.getValue(); + assertEquals(config.getCenterX(), actualConfig.getCenterX(), 0); + assertEquals(config.getCenterY(), actualConfig.getCenterY(), 0); + assertEquals(config.getScale(), actualConfig.getScale(), 0); + } + + + @Test public void onAccessibilityActionPerformed_magnifierEnabled_showMagnificationButton() throws RemoteException { setMagnificationEnabled(MODE_WINDOW); @@ -743,7 +854,7 @@ public class MagnificationControllerTest { } @Test - public void disableWindowMode_windowModeInActive_removeMagnificationButton() + public void disableWindowMode_windowEnabled_removeMagnificationButton() throws RemoteException { setMagnificationEnabled(MODE_WINDOW); @@ -753,7 +864,7 @@ public class MagnificationControllerTest { } @Test - public void onFullScreenDeactivated_fullscreenModeInActive_removeMagnificationButton() + public void onFullScreenDeactivated_fullScreenEnabled_removeMagnificationButton() throws RemoteException { setMagnificationEnabled(MODE_FULLSCREEN); mScreenMagnificationController.setScaleAndCenter(TEST_DISPLAY, @@ -766,7 +877,7 @@ public class MagnificationControllerTest { } @Test - public void transitionToFullScreenMode_fullscreenModeInActive_showMagnificationButton() + public void transitionToFullScreenMode_windowEnabled_showMagnificationButton() throws RemoteException { setMagnificationEnabled(MODE_WINDOW); @@ -779,7 +890,7 @@ public class MagnificationControllerTest { } @Test - public void transitionToWindow_fullscreenModeInActive_showMagnificationButton() + public void transitionToWindow_fullScreenEnabled_showMagnificationButton() throws RemoteException { setMagnificationEnabled(MODE_FULLSCREEN); @@ -1018,7 +1129,6 @@ public class MagnificationControllerTest { reset(); } - final MagnificationConfig config = new MagnificationConfig.Builder().setMode( MODE_FULLSCREEN).setScale(mScale).setCenterX(mCenterX).setCenterY( mCenterY).build(); diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java index e4f1a9645e5c..db1209224bd5 100644 --- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java @@ -28,6 +28,7 @@ import static android.testing.DexmakerShareClassLoaderRule.runWithDexmakerShareC import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; +import static com.android.server.am.UserController.CLEAR_USER_JOURNEY_SESSION_MSG; import static com.android.server.am.UserController.COMPLETE_USER_SWITCH_MSG; import static com.android.server.am.UserController.CONTINUE_USER_SWITCH_MSG; import static com.android.server.am.UserController.REPORT_LOCKED_BOOT_COMPLETE_MSG; @@ -410,6 +411,7 @@ public class UserControllerTest { expectedCodes.add(COMPLETE_USER_SWITCH_MSG); expectedCodes.add(REPORT_USER_SWITCH_COMPLETE_MSG); if (backgroundUserStopping) { + expectedCodes.add(CLEAR_USER_JOURNEY_SESSION_MSG); expectedCodes.add(0); // this is for directly posting in stopping. } Set<Integer> actualCodes = mInjector.mHandler.getMessageCodes(); diff --git a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java index ff8fedce9368..7610b7ca5ec3 100644 --- a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java +++ b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java @@ -28,6 +28,9 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.AppOpsManagerInternal; import android.app.admin.DevicePolicyManagerInternal; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetManagerInternal; @@ -39,11 +42,16 @@ import android.content.ContextWrapper; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.LauncherApps; +import android.content.pm.PackageManagerInternal; import android.content.pm.ShortcutServiceInternal; import android.os.Handler; import android.os.UserHandle; import android.test.InstrumentationTestCase; import android.test.suitebuilder.annotation.SmallTest; +import android.util.AtomicFile; +import android.util.TypedXmlPullParser; +import android.util.TypedXmlSerializer; +import android.util.Xml; import android.widget.RemoteViews; import com.android.frameworks.servicestests.R; @@ -51,9 +59,16 @@ import com.android.internal.appwidget.IAppWidgetHost; import com.android.server.LocalServices; import org.mockito.ArgumentCaptor; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; import java.util.Iterator; import java.util.List; +import java.util.Objects; import java.util.Random; import java.util.concurrent.CountDownLatch; @@ -77,6 +92,8 @@ public class AppWidgetServiceImplTest extends InstrumentationTestCase { private AppWidgetManager mManager; private ShortcutServiceInternal mMockShortcutService; + private PackageManagerInternal mMockPackageManager; + private AppOpsManagerInternal mMockAppOpsManagerInternal; private IAppWidgetHost mMockHost; @Override @@ -85,6 +102,8 @@ public class AppWidgetServiceImplTest extends InstrumentationTestCase { LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); LocalServices.removeServiceForTest(ShortcutServiceInternal.class); LocalServices.removeServiceForTest(AppWidgetManagerInternal.class); + LocalServices.removeServiceForTest(PackageManagerInternal.class); + LocalServices.removeServiceForTest(AppOpsManagerInternal.class); mTestContext = new TestContext(); mPkgName = mTestContext.getOpPackageName(); @@ -92,9 +111,16 @@ public class AppWidgetServiceImplTest extends InstrumentationTestCase { mManager = new AppWidgetManager(mTestContext, mService); mMockShortcutService = mock(ShortcutServiceInternal.class); + mMockPackageManager = mock(PackageManagerInternal.class); + mMockAppOpsManagerInternal = mock(AppOpsManagerInternal.class); mMockHost = mock(IAppWidgetHost.class); LocalServices.addService(ShortcutServiceInternal.class, mMockShortcutService); + LocalServices.addService(PackageManagerInternal.class, mMockPackageManager); + LocalServices.addService(AppOpsManagerInternal.class, mMockAppOpsManagerInternal); + when(mMockPackageManager.filterAppAccess(anyString(), anyInt(), anyInt())) + .thenReturn(false); mService.onStart(); + mService.systemServicesReady(); } public void testLoadDescription() { @@ -323,6 +349,34 @@ public class AppWidgetServiceImplTest extends InstrumentationTestCase { assertThat(info.previewLayout).isEqualTo(R.layout.widget_preview); } + public void testWidgetProviderInfoPersistence() throws IOException { + final AppWidgetProviderInfo original = new AppWidgetProviderInfo(); + original.minWidth = 40; + original.minHeight = 40; + original.maxResizeWidth = 250; + original.maxResizeHeight = 120; + original.targetCellWidth = 1; + original.targetCellHeight = 1; + original.updatePeriodMillis = 86400000; + original.previewLayout = R.layout.widget_preview; + original.label = "test"; + + final File file = new File(mTestContext.getDataDir(), "appwidget_provider_info.xml"); + saveWidgetProviderInfoLocked(file, original); + final AppWidgetProviderInfo target = loadAppWidgetProviderInfoLocked(file); + + assertThat(target.minWidth).isEqualTo(original.minWidth); + assertThat(target.minHeight).isEqualTo(original.minHeight); + assertThat(target.minResizeWidth).isEqualTo(original.minResizeWidth); + assertThat(target.minResizeHeight).isEqualTo(original.minResizeHeight); + assertThat(target.maxResizeWidth).isEqualTo(original.maxResizeWidth); + assertThat(target.maxResizeHeight).isEqualTo(original.maxResizeHeight); + assertThat(target.targetCellWidth).isEqualTo(original.targetCellWidth); + assertThat(target.targetCellHeight).isEqualTo(original.targetCellHeight); + assertThat(target.updatePeriodMillis).isEqualTo(original.updatePeriodMillis); + assertThat(target.previewLayout).isEqualTo(original.previewLayout); + } + private int setupHostAndWidget() { List<PendingHostUpdate> updates = mService.startListening( mMockHost, mPkgName, HOST_ID, new int[0]).getList(); @@ -353,6 +407,44 @@ public class AppWidgetServiceImplTest extends InstrumentationTestCase { return mTestContext.getResources().getInteger(resId); } + private static void saveWidgetProviderInfoLocked(@NonNull final File dst, + @Nullable final AppWidgetProviderInfo info) + throws IOException { + Objects.requireNonNull(dst); + if (info == null) { + return; + } + final AtomicFile file = new AtomicFile(dst); + final FileOutputStream stream = file.startWrite(); + final TypedXmlSerializer out = Xml.resolveSerializer(stream); + out.startDocument(null, true); + out.startTag(null, "p"); + AppWidgetXmlUtil.writeAppWidgetProviderInfoLocked(out, info); + out.endTag(null, "p"); + out.endDocument(); + file.finishWrite(stream); + } + + public static AppWidgetProviderInfo loadAppWidgetProviderInfoLocked(@NonNull final File dst) { + Objects.requireNonNull(dst); + final AtomicFile file = new AtomicFile(dst); + try (FileInputStream stream = file.openRead()) { + final TypedXmlPullParser parser = Xml.resolvePullParser(stream); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && type != XmlPullParser.START_TAG) { + // drain whitespace, comments, etc. + } + final String nodeName = parser.getName(); + if (!"p".equals(nodeName)) { + return null; + } + return AppWidgetXmlUtil.readAppWidgetProviderInfoLocked(parser); + } catch (IOException | XmlPullParserException e) { + return null; + } + } + private class TestContext extends ContextWrapper { public TestContext() { diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallbackTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java index 38e8dfa45262..5f88c99b1d1e 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallbackTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java @@ -24,12 +24,13 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.hardware.fingerprint.FingerprintStateListener; +import android.hardware.biometrics.BiometricStateListener; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; import com.android.server.biometrics.sensors.AuthenticationClient; +import com.android.server.biometrics.sensors.BiometricStateCallback; import com.android.server.biometrics.sensors.EnrollClient; import org.junit.Before; @@ -39,19 +40,19 @@ import org.mockito.MockitoAnnotations; @Presubmit @SmallTest -public class FingerprintStateCallbackTest { +public class BiometricStateCallbackTest { - private FingerprintStateCallback mCallback; + private BiometricStateCallback mCallback; @Mock - FingerprintStateListener mFingerprintStateListener; + BiometricStateListener mBiometricStateListener; @Before public void setup() { MockitoAnnotations.initMocks(this); - mCallback = new FingerprintStateCallback(); - mCallback.registerFingerprintStateListener(mFingerprintStateListener); + mCallback = new BiometricStateCallback(); + mCallback.registerBiometricStateListener(mBiometricStateListener); } @Test @@ -86,10 +87,10 @@ public class FingerprintStateCallbackTest { mCallback.onClientFinished(client, true /* success */); if (expectCallback) { - verify(mFingerprintStateListener).onEnrollmentsChanged(eq(userId), eq(sensorId), + verify(mBiometricStateListener).onEnrollmentsChanged(eq(userId), eq(sensorId), eq(expectedCallbackValue)); } else { - verify(mFingerprintStateListener, never()).onEnrollmentsChanged(anyInt(), anyInt(), + verify(mBiometricStateListener, never()).onEnrollmentsChanged(anyInt(), anyInt(), anyBoolean()); } } @@ -98,7 +99,7 @@ public class FingerprintStateCallbackTest { public void testAuthentication_enrollmentCallbackNeverNotified() { AuthenticationClient<?> client = mock(AuthenticationClient.class); mCallback.onClientFinished(client, true /* success */); - verify(mFingerprintStateListener, never()).onEnrollmentsChanged(anyInt(), anyInt(), + verify(mBiometricStateListener, never()).onEnrollmentsChanged(anyInt(), anyInt(), anyBoolean()); } } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java index 5a1a02eb39c8..c6ddf27f96b2 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java @@ -42,9 +42,9 @@ import androidx.test.filters.SmallTest; import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.sensors.BiometricScheduler; +import com.android.server.biometrics.sensors.BiometricStateCallback; import com.android.server.biometrics.sensors.HalClientMonitor; import com.android.server.biometrics.sensors.LockoutResetDispatcher; -import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback; import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher; import org.junit.Before; @@ -71,7 +71,7 @@ public class FingerprintProviderTest { @Mock private GestureAvailabilityDispatcher mGestureAvailabilityDispatcher; @Mock - private FingerprintStateCallback mFingerprintStateCallback; + private BiometricStateCallback mBiometricStateCallback; @Mock private BiometricContext mBiometricContext; @@ -107,7 +107,7 @@ public class FingerprintProviderTest { mLockoutResetDispatcher = new LockoutResetDispatcher(mContext); mFingerprintProvider = new TestableFingerprintProvider(mDaemon, mContext, - mFingerprintStateCallback, mSensorProps, TAG, mLockoutResetDispatcher, + mBiometricStateCallback, mSensorProps, TAG, mLockoutResetDispatcher, mGestureAvailabilityDispatcher, mBiometricContext); } @@ -156,13 +156,13 @@ public class FingerprintProviderTest { TestableFingerprintProvider(@NonNull IFingerprint daemon, @NonNull Context context, - @NonNull FingerprintStateCallback fingerprintStateCallback, + @NonNull BiometricStateCallback biometricStateCallback, @NonNull SensorProps[] props, @NonNull String halInstanceName, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher, @NonNull BiometricContext biometricContext) { - super(context, fingerprintStateCallback, props, halInstanceName, lockoutResetDispatcher, + super(context, biometricStateCallback, props, halInstanceName, lockoutResetDispatcher, gestureAvailabilityDispatcher, biometricContext); mDaemon = daemon; } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java index 529f994f2773..b32b89aaefb0 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java @@ -41,8 +41,8 @@ import androidx.test.filters.SmallTest; import com.android.internal.R; import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.sensors.BiometricScheduler; +import com.android.server.biometrics.sensors.BiometricStateCallback; import com.android.server.biometrics.sensors.LockoutResetDispatcher; -import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback; import org.junit.Before; import org.junit.Test; @@ -70,7 +70,7 @@ public class Fingerprint21Test { @Mock private BiometricScheduler mScheduler; @Mock - private FingerprintStateCallback mFingerprintStateCallback; + private BiometricStateCallback mBiometricStateCallback; @Mock private BiometricContext mBiometricContext; @@ -102,7 +102,7 @@ public class Fingerprint21Test { componentInfo, FingerprintSensorProperties.TYPE_UNKNOWN, resetLockoutRequiresHardwareAuthToken); - mFingerprint21 = new TestableFingerprint21(mContext, mFingerprintStateCallback, sensorProps, + mFingerprint21 = new TestableFingerprint21(mContext, mBiometricStateCallback, sensorProps, mScheduler, new Handler(Looper.getMainLooper()), mLockoutResetDispatcher, mHalResultController, mBiometricContext); } @@ -125,13 +125,13 @@ public class Fingerprint21Test { private static class TestableFingerprint21 extends Fingerprint21 { TestableFingerprint21(@NonNull Context context, - @NonNull FingerprintStateCallback fingerprintStateCallback, + @NonNull BiometricStateCallback biometricStateCallback, @NonNull FingerprintSensorPropertiesInternal sensorProps, @NonNull BiometricScheduler scheduler, @NonNull Handler handler, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull HalResultController controller, @NonNull BiometricContext biometricContext) { - super(context, fingerprintStateCallback, sensorProps, scheduler, handler, + super(context, biometricStateCallback, sensorProps, scheduler, handler, lockoutResetDispatcher, controller, biometricContext); } diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java index d1b015674b3a..808f8c2cc626 100644 --- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java @@ -92,6 +92,7 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.Arrays; +import java.util.function.Consumer; @Presubmit @RunWith(AndroidTestingRunner.class) @@ -133,6 +134,8 @@ public class VirtualDeviceManagerServiceTest { @Mock private IVirtualDeviceActivityListener mActivityListener; @Mock + private Consumer<ArraySet<Integer>> mRunningAppsChangedCallback; + @Mock IPowerManager mIPowerManagerMock; @Mock IThermalService mIThermalServiceMock; @@ -207,7 +210,7 @@ public class VirtualDeviceManagerServiceTest { mDeviceImpl = new VirtualDeviceImpl(mContext, mAssociationInfo, new Binder(), /* uid */ 0, mInputController, (int associationId) -> { - }, mPendingTrampolineCallback, mActivityListener, + }, mPendingTrampolineCallback, mActivityListener, mRunningAppsChangedCallback, params); } diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java index f834b3438aa3..8bb619f1976a 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java @@ -27,19 +27,15 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.admin.DevicePolicyManager; -import android.app.admin.DevicePolicyManagerInternal; -import android.app.admin.DevicePolicyManagerLiteInternal; import android.content.ComponentName; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Build; -import android.os.Bundle; import android.os.IpcDataCache; import android.os.UserHandle; import android.os.UserManager; @@ -50,7 +46,6 @@ import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.frameworks.servicestests.R; -import com.android.server.LocalServices; import com.android.server.SystemService; import org.junit.Before; @@ -58,8 +53,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.io.File; -import java.util.HashMap; -import java.util.Map; import java.util.Set; @Presubmit @@ -90,232 +83,9 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { .thenReturn(true); } - @Test - public void testMigration() throws Exception { - final File user10dir = getServices().addUser(10, 0, USER_TYPE_EMPTY); - final File user11dir = getServices().addUser(11, 0, - UserManager.USER_TYPE_PROFILE_MANAGED); - getServices().addUser(12, 0, USER_TYPE_EMPTY); - - setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID); - setUpPackageManagerForAdmin(admin2, UserHandle.getUid(10, 123)); - setUpPackageManagerForAdmin(admin3, UserHandle.getUid(11, 456)); - - // Create the legacy owners & policies file. - DpmTestUtils.writeToFile( - (new File(getServices().dataDir, "device_owner.xml")).getAbsoluteFile(), - DpmTestUtils.readAsset(mRealTestContext, - "DevicePolicyManagerServiceMigrationTest/legacy_device_owner.xml")); - - DpmTestUtils.writeToFile( - (new File(getServices().systemUserDataDir, "device_policies.xml")).getAbsoluteFile(), - DpmTestUtils.readAsset(mRealTestContext, - "DevicePolicyManagerServiceMigrationTest/legacy_device_policies.xml")); - - DpmTestUtils.writeToFile( - (new File(user10dir, "device_policies.xml")).getAbsoluteFile(), - DpmTestUtils.readAsset(mRealTestContext, - "DevicePolicyManagerServiceMigrationTest/legacy_device_policies_10.xml")); - DpmTestUtils.writeToFile( - (new File(user11dir, "device_policies.xml")).getAbsoluteFile(), - DpmTestUtils.readAsset(mRealTestContext, - "DevicePolicyManagerServiceMigrationTest/legacy_device_policies_11.xml")); - - // Set up UserManager - when(getServices().userManagerInternal.getBaseUserRestrictions( - eq(USER_SYSTEM))).thenReturn(DpmTestUtils.newRestrictions( - UserManager.DISALLOW_ADD_USER, - UserManager.DISALLOW_RECORD_AUDIO)); - - when(getServices().userManagerInternal.getBaseUserRestrictions( - eq(10))).thenReturn(DpmTestUtils.newRestrictions( - UserManager.DISALLOW_REMOVE_USER, - UserManager.DISALLOW_ADD_USER, - UserManager.DISALLOW_SMS, - UserManager.DISALLOW_OUTGOING_CALLS, - UserManager.DISALLOW_WALLPAPER, - UserManager.DISALLOW_RECORD_AUDIO)); - - when(getServices().userManagerInternal.getBaseUserRestrictions( - eq(11))).thenReturn(DpmTestUtils.newRestrictions( - UserManager.DISALLOW_REMOVE_USER, - UserManager.DISALLOW_ADD_USER, - UserManager.DISALLOW_SMS, - UserManager.DISALLOW_OUTGOING_CALLS, - UserManager.DISALLOW_WALLPAPER, - UserManager.DISALLOW_RECORD_AUDIO)); - - final Map<Integer, Bundle> newBaseRestrictions = new HashMap<>(); - - doAnswer(invocation -> { - Integer userId = (Integer) invocation.getArguments()[0]; - Bundle bundle = (Bundle) invocation.getArguments()[1]; - - newBaseRestrictions.put(userId, bundle); - - return null; - }).when(getServices().userManagerInternal).setBaseUserRestrictionsByDpmsForMigration( - anyInt(), any(Bundle.class)); - - // Initialize DPM/DPMS and let it migrate the persisted information. - // (Need clearCallingIdentity() to pass permission checks.) - - final DevicePolicyManagerServiceTestable dpms; - - final long ident = mContext.binder.clearCallingIdentity(); - try { - LocalServices.removeServiceForTest(DevicePolicyManagerLiteInternal.class); - LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); - - dpms = new DevicePolicyManagerServiceTestable(getServices(), mContext); - - dpms.systemReady(SystemService.PHASE_LOCK_SETTINGS_READY); - dpms.systemReady(SystemService.PHASE_BOOT_COMPLETED); - } finally { - mContext.binder.restoreCallingIdentity(ident); - } - - assertThat(dpms.mOwners.hasDeviceOwner()).isTrue(); - assertThat(dpms.mOwners.hasProfileOwner(USER_SYSTEM)).isFalse(); - assertThat(dpms.mOwners.hasProfileOwner(10)).isTrue(); - assertThat(dpms.mOwners.hasProfileOwner(11)).isTrue(); - assertThat(dpms.mOwners.hasProfileOwner(12)).isFalse(); - - // Now all information should be migrated. - assertThat(dpms.mOwners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse(); - assertThat(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(USER_SYSTEM)) - .isFalse(); - assertThat(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse(); - assertThat(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse(); - assertThat(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(12)).isFalse(); - - // Check the new base restrictions. - DpmTestUtils.assertRestrictions( - DpmTestUtils.newRestrictions( - UserManager.DISALLOW_RECORD_AUDIO - ), - newBaseRestrictions.get(USER_SYSTEM)); - - DpmTestUtils.assertRestrictions( - DpmTestUtils.newRestrictions( - UserManager.DISALLOW_ADD_USER, - UserManager.DISALLOW_SMS, - UserManager.DISALLOW_OUTGOING_CALLS, - UserManager.DISALLOW_RECORD_AUDIO, - UserManager.DISALLOW_WALLPAPER - ), - newBaseRestrictions.get(10)); - - DpmTestUtils.assertRestrictions( - DpmTestUtils.newRestrictions( - UserManager.DISALLOW_ADD_USER, - UserManager.DISALLOW_SMS, - UserManager.DISALLOW_OUTGOING_CALLS, - UserManager.DISALLOW_WALLPAPER, - UserManager.DISALLOW_RECORD_AUDIO - ), - newBaseRestrictions.get(11)); - - // Check the new owner restrictions. - DpmTestUtils.assertRestrictions( - DpmTestUtils.newRestrictions( - UserManager.DISALLOW_ADD_USER - ), - dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()); - - DpmTestUtils.assertRestrictions( - DpmTestUtils.newRestrictions( - UserManager.DISALLOW_REMOVE_USER - ), - dpms.getProfileOwnerAdminLocked(10).ensureUserRestrictions()); - - DpmTestUtils.assertRestrictions( - DpmTestUtils.newRestrictions( - UserManager.DISALLOW_REMOVE_USER - ), - dpms.getProfileOwnerAdminLocked(11).ensureUserRestrictions()); - } - - @Test - public void testMigration2_profileOwnerOnUser0() throws Exception { - setUpPackageManagerForAdmin(admin2, DpmMockContext.CALLER_SYSTEM_USER_UID); - - // Create the legacy owners & policies file. - DpmTestUtils.writeToFile( - (new File(getServices().dataDir, "device_owner.xml")).getAbsoluteFile(), - DpmTestUtils.readAsset(mRealTestContext, - "DevicePolicyManagerServiceMigrationTest2/legacy_device_owner.xml")); - - DpmTestUtils.writeToFile( - (new File(getServices().systemUserDataDir, "device_policies.xml")).getAbsoluteFile(), - DpmTestUtils.readAsset(mRealTestContext, - "DevicePolicyManagerServiceMigrationTest2/legacy_device_policies.xml")); - - // Set up UserManager - when(getServices().userManagerInternal.getBaseUserRestrictions( - eq(USER_SYSTEM))).thenReturn(DpmTestUtils.newRestrictions( - UserManager.DISALLOW_ADD_USER, - UserManager.DISALLOW_RECORD_AUDIO, - UserManager.DISALLOW_SMS, - UserManager.DISALLOW_OUTGOING_CALLS)); - - final Map<Integer, Bundle> newBaseRestrictions = new HashMap<>(); - - doAnswer(invocation -> { - Integer userId = (Integer) invocation.getArguments()[0]; - Bundle bundle = (Bundle) invocation.getArguments()[1]; - - newBaseRestrictions.put(userId, bundle); - - return null; - }).when(getServices().userManagerInternal).setBaseUserRestrictionsByDpmsForMigration( - anyInt(), any(Bundle.class)); - - // Initialize DPM/DPMS and let it migrate the persisted information. - // (Need clearCallingIdentity() to pass permission checks.) - - final DevicePolicyManagerServiceTestable dpms; - - final long ident = mContext.binder.clearCallingIdentity(); - try { - LocalServices.removeServiceForTest(DevicePolicyManagerLiteInternal.class); - LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); - - dpms = new DevicePolicyManagerServiceTestable(getServices(), mContext); - - dpms.systemReady(SystemService.PHASE_LOCK_SETTINGS_READY); - dpms.systemReady(SystemService.PHASE_BOOT_COMPLETED); - } finally { - mContext.binder.restoreCallingIdentity(ident); - } - assertThat(dpms.mOwners.hasDeviceOwner()).isFalse(); - assertThat(dpms.mOwners.hasProfileOwner(USER_SYSTEM)).isTrue(); - - // Now all information should be migrated. - assertThat(dpms.mOwners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse(); - assertThat(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(USER_SYSTEM)) - .isFalse(); - - // Check the new base restrictions. - DpmTestUtils.assertRestrictions( - DpmTestUtils.newRestrictions( - UserManager.DISALLOW_RECORD_AUDIO - ), - newBaseRestrictions.get(USER_SYSTEM)); - - // Check the new owner restrictions. - DpmTestUtils.assertRestrictions( - DpmTestUtils.newRestrictions( - UserManager.DISALLOW_ADD_USER, - UserManager.DISALLOW_SMS, - UserManager.DISALLOW_OUTGOING_CALLS - ), - dpms.getProfileOwnerAdminLocked(USER_SYSTEM).ensureUserRestrictions()); - } - // Test setting default restrictions for managed profile. @Test - public void testMigration3_managedProfileOwner() throws Exception { + public void testMigration_managedProfileOwner() throws Exception { // Create a managed profile user. final File user10dir = getServices().addUser(10, 0, UserManager.USER_TYPE_PROFILE_MANAGED); @@ -347,9 +117,6 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { // (Need clearCallingIdentity() to pass permission checks.) final long ident = mContext.binder.clearCallingIdentity(); try { - LocalServices.removeServiceForTest(DevicePolicyManagerLiteInternal.class); - LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); - dpms = new DevicePolicyManagerServiceTestable(getServices(), mContext); dpms.systemReady(SystemService.PHASE_LOCK_SETTINGS_READY); @@ -508,9 +275,6 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { DevicePolicyManagerServiceTestable dpms; final long ident = mContext.binder.clearCallingIdentity(); try { - LocalServices.removeServiceForTest(DevicePolicyManagerLiteInternal.class); - LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); - dpms = new DevicePolicyManagerServiceTestable(getServices(), mContext); dpms.systemReady(SystemService.PHASE_LOCK_SETTINGS_READY); diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java index 4f87f9d949eb..2dbf728c577e 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java @@ -21,6 +21,8 @@ import android.app.IActivityManager; import android.app.IActivityTaskManager; import android.app.NotificationManager; import android.app.PendingIntent; +import android.app.admin.DevicePolicyManagerInternal; +import android.app.admin.DevicePolicyManagerLiteInternal; import android.app.backup.IBackupManager; import android.app.usage.UsageStatsManagerInternal; import android.content.Context; @@ -49,6 +51,7 @@ import androidx.annotation.NonNull; import com.android.internal.util.FunctionalUtils.ThrowingRunnable; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockSettingsInternal; +import com.android.server.LocalServices; import com.android.server.PersistentDataBlockManagerInternal; import com.android.server.net.NetworkPolicyManagerInternal; import com.android.server.pm.UserManagerInternal; @@ -99,11 +102,22 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi } private DevicePolicyManagerServiceTestable(MockInjector injector) { - super(injector); + super(unregisterLocalServices(injector)); mMockInjector = injector; this.context = injector.context; } + /** + * Unregisters local services to avoid IllegalStateException when DPMS ctor re-registers them. + * This is made into a static method to circumvent the requirement to call super() first. + * Returns its parameter as is. + */ + private static MockInjector unregisterLocalServices(MockInjector injector) { + LocalServices.removeServiceForTest(DevicePolicyManagerLiteInternal.class); + LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); + return injector; + } + public void notifyChangeToContentObserver(Uri uri, int userHandle) { ContentObserver co = mMockInjector.mContentObservers.get(new Pair<>(uri, userHandle)); if (co != null) { diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index ea136da5f323..45d101a4a426 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -328,8 +328,6 @@ public class DevicePolicyManagerTest extends DpmTestBase { private void initializeDpms() { // Need clearCallingIdentity() to pass permission checks. final long ident = mContext.binder.clearCallingIdentity(); - LocalServices.removeServiceForTest(DevicePolicyManagerLiteInternal.class); - LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); dpms = new DevicePolicyManagerServiceTestable(getServices(), mContext); dpms.systemReady(SystemService.PHASE_LOCK_SETTINGS_READY); @@ -417,8 +415,6 @@ public class DevicePolicyManagerTest extends DpmTestBase { when(getServices().packageManager.hasSystemFeature(eq(PackageManager.FEATURE_DEVICE_ADMIN))) .thenReturn(false); - LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); - LocalServices.removeServiceForTest(DevicePolicyManagerLiteInternal.class); new DevicePolicyManagerServiceTestable(getServices(), mContext); // If the device has no DPMS feature, it shouldn't register the local service. @@ -1669,39 +1665,6 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertThat(deviceOwner.getUid()).isEqualTo(DpmMockContext.CALLER_SYSTEM_USER_UID); } - /** - * This essentially tests - * {@code DevicePolicyManagerService.findOwnerComponentIfNecessaryLocked()}. (which is - * private.) - * - * We didn't use to persist the DO component class name, but now we do, and the above method - * finds the right component from a package name upon migration. - */ - @Test - public void testDeviceOwnerMigration() throws Exception { - checkDeviceOwnerWithMultipleDeviceAdmins(); - - // Overwrite the device owner setting and clears the class name. - dpms.mOwners.setDeviceOwner( - new ComponentName(admin2.getPackageName(), ""), - "owner-name", CALLER_USER_HANDLE); - dpms.mOwners.writeDeviceOwner(); - - // Make sure the DO component name doesn't have a class name. - assertThat(dpms.getDeviceOwnerComponent(/* callingUserOnly= */ false).getClassName()) - .isEmpty(); - - // Then create a new DPMS to have it load the settings from files. - when(getServices().userManager.getUserRestrictions(any(UserHandle.class))) - .thenReturn(new Bundle()); - initializeDpms(); - - // Now the DO component name is a full name. - // *BUT* because both admin1 and admin2 belong to the same package, we think admin1 is the - // DO. - assertThat(dpms.getDeviceOwnerComponent(/* callingUserOnly =*/ false)).isEqualTo(admin1); - } - @Test public void testSetGetApplicationRestriction() { setAsProfileOwner(admin1); diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java index 69aaf010d0e0..d55f3796f6cb 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java @@ -27,7 +27,6 @@ import static org.mockito.Mockito.verify; import android.app.admin.ConnectEvent; import android.app.admin.DeviceAdminReceiver; -import android.app.admin.DevicePolicyManagerInternal; import android.app.admin.DnsEvent; import android.app.admin.NetworkEvent; import android.content.Intent; @@ -40,8 +39,6 @@ import android.os.UserHandle; import android.os.test.TestLooper; import android.test.suitebuilder.annotation.SmallTest; -import com.android.server.LocalServices; - import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -66,7 +63,6 @@ public class NetworkEventTest extends DpmTestBase { android.Manifest.permission.MANAGE_DEVICE_ADMINS); doNothing().when(mSpiedDpmMockContext).sendBroadcastAsUser(any(Intent.class), any(UserHandle.class)); - LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class); mDpmTestable = new DevicePolicyManagerServiceTestable(getServices(), mSpiedDpmMockContext); setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_UID); mDpmTestable.setActiveAdmin(admin1, true, DpmMockContext.CALLER_USER_HANDLE); diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java index d1706f857c13..37ba8a42da86 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java @@ -18,29 +18,22 @@ package com.android.server.devicepolicy; import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT; import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED; +import static android.app.admin.SystemUpdatePolicy.TYPE_INSTALL_WINDOWED; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.verify; - import android.content.ComponentName; import android.os.IpcDataCache; -import android.os.UserHandle; import android.test.suitebuilder.annotation.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.server.devicepolicy.DevicePolicyManagerServiceTestable.OwnersTestable; -import com.google.android.collect.Lists; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import java.util.ArrayList; -import java.util.List; - /** * Tests for the DeviceOwner object that saves & loads device and policy owner information. * @@ -52,8 +45,7 @@ import java.util.List; @RunWith(AndroidJUnit4.class) public class OwnersTest extends DpmTestBase { - private static final List<String> DEVICE_OWNER_PROTECTED_PACKAGES = - Lists.newArrayList("package_1", "package_2"); + private static final String TESTDPC_PACKAGE = "com.afwsamples.testdpc"; @Before public void setUp() throws Exception { @@ -63,572 +55,66 @@ public class OwnersTest extends DpmTestBase { } @Test - public void testUpgrade01() throws Exception { - getServices().addUsers(10, 11, 20, 21); - - // First, migrate. - { - final OwnersTestable owners = new OwnersTestable(getServices()); - - DpmTestUtils.writeToFile(owners.getLegacyConfigFile(), - DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/test01/input.xml")); - - owners.load(); - - // The legacy file should be removed. - assertThat(owners.getLegacyConfigFile().exists()).isFalse(); - - // File was empty, so no new files should be created. - assertThat(owners.getDeviceOwnerFile().exists()).isFalse(); - - assertThat(owners.getProfileOwnerFile(10).exists()).isFalse(); - assertThat(owners.getProfileOwnerFile(11).exists()).isFalse(); - assertThat(owners.getProfileOwnerFile(20).exists()).isFalse(); - assertThat(owners.getProfileOwnerFile(21).exists()).isFalse(); - - assertThat(owners.hasDeviceOwner()).isFalse(); - assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL); - assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo( - DEVICE_OWNER_TYPE_DEFAULT); - assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName())) - .isEmpty(); - assertThat(owners.getSystemUpdatePolicy()).isNull(); - assertThat(owners.getProfileOwnerKeys()).isEmpty(); - - assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse(); - - owners.setDeviceOwnerType(owners.getDeviceOwnerPackageName(), - DEVICE_OWNER_TYPE_FINANCED, /* isAdminTestOnly= */ false); - // There is no device owner, so the default owner type should be returned. - assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo( - DEVICE_OWNER_TYPE_DEFAULT); - } - - // Then re-read and check. - { - final OwnersTestable owners = new OwnersTestable(getServices()); - owners.load(); - - assertThat(owners.hasDeviceOwner()).isFalse(); - assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL); - assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo( - DEVICE_OWNER_TYPE_DEFAULT); - assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName())) - .isEmpty(); - assertThat(owners.getSystemUpdatePolicy()).isNull(); - assertThat(owners.getProfileOwnerKeys()).isEmpty(); - - assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse(); - } - } - - @Test - public void testUpgrade02() throws Exception { - getServices().addUsers(10, 11, 20, 21); - - // First, migrate. - { - final OwnersTestable owners = new OwnersTestable(getServices()); - - DpmTestUtils.writeToFile(owners.getLegacyConfigFile(), - DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/test02/input.xml")); - - owners.load(); - - // The legacy file should be removed. - assertThat(owners.getLegacyConfigFile().exists()).isFalse(); - - assertThat(owners.getDeviceOwnerFile().exists()).isTrue(); // TODO Check content - - assertThat(owners.getProfileOwnerFile(10).exists()).isFalse(); - assertThat(owners.getProfileOwnerFile(11).exists()).isFalse(); - assertThat(owners.getProfileOwnerFile(20).exists()).isFalse(); - assertThat(owners.getProfileOwnerFile(21).exists()).isFalse(); - - assertThat(owners.hasDeviceOwner()).isTrue(); - assertThat(owners.getDeviceOwnerName()).isEqualTo(null); - assertThat(owners.getDeviceOwnerPackageName()).isEqualTo("com.google.android.testdpc"); - assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM); - assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo( - DEVICE_OWNER_TYPE_DEFAULT); - assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName())) - .isEmpty(); - - assertThat(owners.getSystemUpdatePolicy()).isNull(); - assertThat(owners.getProfileOwnerKeys()).isEmpty(); - - assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isTrue(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse(); - } - - // Then re-read and check. - { - final OwnersTestable owners = new OwnersTestable(getServices()); - owners.load(); - - assertThat(owners.hasDeviceOwner()).isTrue(); - assertThat(owners.getDeviceOwnerName()).isEqualTo(null); - assertThat(owners.getDeviceOwnerPackageName()).isEqualTo("com.google.android.testdpc"); - assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM); - assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo( - DEVICE_OWNER_TYPE_DEFAULT); - assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName())) - .isEmpty(); - - assertThat(owners.getSystemUpdatePolicy()).isNull(); - assertThat(owners.getProfileOwnerKeys()).isEmpty(); - - assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isTrue(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse(); - } - } - - @Test - public void testUpgrade03() throws Exception { - getServices().addUsers(10, 11, 20, 21); - - // First, migrate. - { - final OwnersTestable owners = new OwnersTestable(getServices()); - - DpmTestUtils.writeToFile(owners.getLegacyConfigFile(), - DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/test03/input.xml")); - - owners.load(); - - // The legacy file should be removed. - assertThat(owners.getLegacyConfigFile().exists()).isFalse(); - - assertThat(owners.getDeviceOwnerFile().exists()).isFalse(); - - assertThat(owners.getProfileOwnerFile(10).exists()).isTrue(); - assertThat(owners.getProfileOwnerFile(11).exists()).isTrue(); - assertThat(owners.getProfileOwnerFile(20).exists()).isFalse(); - assertThat(owners.getProfileOwnerFile(21).exists()).isFalse(); - - assertThat(owners.hasDeviceOwner()).isFalse(); - assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL); - assertThat(owners.getSystemUpdatePolicy()).isNull(); - assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo( - DEVICE_OWNER_TYPE_DEFAULT); - assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName())) - .isEmpty(); - - assertThat(owners.getProfileOwnerKeys()).hasSize(2); - assertThat(owners.getProfileOwnerComponent(10)) - .isEqualTo(new ComponentName("com.google.android.testdpc", - "com.google.android.testdpc.DeviceAdminReceiver0")); - assertThat(owners.getProfileOwnerName(10)).isEqualTo("0"); - assertThat(owners.getProfileOwnerPackage(10)).isEqualTo("com.google.android.testdpc"); - - assertThat(owners.getProfileOwnerComponent(11)) - .isEqualTo(new ComponentName("com.google.android.testdpc1", "")); - assertThat(owners.getProfileOwnerName(11)).isEqualTo("1"); - assertThat(owners.getProfileOwnerPackage(11)).isEqualTo("com.google.android.testdpc1"); - - assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isTrue(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse(); - } - - // Then re-read and check. - { - final OwnersTestable owners = new OwnersTestable(getServices()); - owners.load(); - - assertThat(owners.hasDeviceOwner()).isFalse(); - assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL); - assertThat(owners.getSystemUpdatePolicy()).isNull(); - assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo( - DEVICE_OWNER_TYPE_DEFAULT); - assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName())) - .isEmpty(); - - assertThat(owners.getProfileOwnerKeys()).hasSize(2); - assertThat(owners.getProfileOwnerComponent(10)) - .isEqualTo(new ComponentName("com.google.android.testdpc", - "com.google.android.testdpc.DeviceAdminReceiver0")); - assertThat(owners.getProfileOwnerName(10)).isEqualTo("0"); - assertThat(owners.getProfileOwnerPackage(10)).isEqualTo("com.google.android.testdpc"); - - assertThat(owners.getProfileOwnerComponent(11)) - .isEqualTo(new ComponentName("com.google.android.testdpc1", "")); - assertThat(owners.getProfileOwnerName(11)).isEqualTo("1"); - assertThat(owners.getProfileOwnerPackage(11)).isEqualTo("com.google.android.testdpc1"); - - assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isTrue(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse(); - } - } - - /** - * Note this also tests {@link Owners#setDeviceOwnerUserRestrictionsMigrated()} - * and {@link Owners#setProfileOwnerUserRestrictionsMigrated(int)}. - */ - @Test - public void testUpgrade04() throws Exception { - getServices().addUsers(10, 11, 20, 21); - - // First, migrate. - { - final OwnersTestable owners = new OwnersTestable(getServices()); - - DpmTestUtils.writeToFile(owners.getLegacyConfigFile(), - DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/test04/input.xml")); - - owners.load(); - - // The legacy file should be removed. - assertThat(owners.getLegacyConfigFile().exists()).isFalse(); - - assertThat(owners.getDeviceOwnerFile().exists()).isTrue(); - - assertThat(owners.getProfileOwnerFile(10).exists()).isTrue(); - assertThat(owners.getProfileOwnerFile(11).exists()).isTrue(); - assertThat(owners.getProfileOwnerFile(20).exists()).isFalse(); - assertThat(owners.getProfileOwnerFile(21).exists()).isFalse(); - - assertThat(owners.hasDeviceOwner()).isTrue(); - assertThat(owners.getDeviceOwnerName()).isEqualTo(null); - assertThat(owners.getDeviceOwnerPackageName()).isEqualTo("com.google.android.testdpc"); - assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM); - assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo( - DEVICE_OWNER_TYPE_DEFAULT); - assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName())) - .isEmpty(); - - assertThat(owners.getSystemUpdatePolicy()).isNotNull(); - assertThat(owners.getSystemUpdatePolicy().getPolicyType()).isEqualTo(5); - - assertThat(owners.getProfileOwnerKeys()).hasSize(2); - assertThat(owners.getProfileOwnerComponent(10)) - .isEqualTo(new ComponentName("com.google.android.testdpc", - "com.google.android.testdpc.DeviceAdminReceiver0")); - assertThat(owners.getProfileOwnerName(10)).isEqualTo("0"); - assertThat(owners.getProfileOwnerPackage(10)).isEqualTo("com.google.android.testdpc"); - - assertThat(owners.getProfileOwnerComponent(11)) - .isEqualTo(new ComponentName("com.google.android.testdpc1", "")); - assertThat(owners.getProfileOwnerName(11)).isEqualTo("1"); - assertThat(owners.getProfileOwnerPackage(11)).isEqualTo("com.google.android.testdpc1"); - - assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isTrue(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isTrue(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse(); - } - - // Then re-read and check. - { - final OwnersTestable owners = new OwnersTestable(getServices()); - owners.load(); - - assertThat(owners.hasDeviceOwner()).isTrue(); - assertThat(owners.getDeviceOwnerName()).isEqualTo(null); - assertThat(owners.getDeviceOwnerPackageName()).isEqualTo("com.google.android.testdpc"); - assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM); - assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo( - DEVICE_OWNER_TYPE_DEFAULT); - assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName())) - .isEmpty(); - - assertThat(owners.getSystemUpdatePolicy()).isNotNull(); - assertThat(owners.getSystemUpdatePolicy().getPolicyType()).isEqualTo(5); - - assertThat(owners.getProfileOwnerKeys()).hasSize(2); - assertThat(owners.getProfileOwnerComponent(10)) - .isEqualTo(new ComponentName("com.google.android.testdpc", - "com.google.android.testdpc.DeviceAdminReceiver0")); - assertThat(owners.getProfileOwnerName(10)).isEqualTo("0"); - assertThat(owners.getProfileOwnerPackage(10)).isEqualTo("com.google.android.testdpc"); - - assertThat(owners.getProfileOwnerComponent(11)) - .isEqualTo(new ComponentName("com.google.android.testdpc1", "")); - assertThat(owners.getProfileOwnerName(11)).isEqualTo("1"); - assertThat(owners.getProfileOwnerPackage(11)).isEqualTo("com.google.android.testdpc1"); - - assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isTrue(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isTrue(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse(); - - owners.setDeviceOwnerUserRestrictionsMigrated(); - - owners.setDeviceOwnerType(owners.getDeviceOwnerPackageName(), - DEVICE_OWNER_TYPE_FINANCED, /* isAdminTestOnly= */ false); - assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo( - DEVICE_OWNER_TYPE_FINANCED); - - owners.setDeviceOwnerProtectedPackages( - owners.getDeviceOwnerPackageName(), DEVICE_OWNER_PROTECTED_PACKAGES); - assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName())) - .isEqualTo(DEVICE_OWNER_PROTECTED_PACKAGES); - verify(getServices().packageManagerInternal) - .setDeviceOwnerProtectedPackages( - owners.getDeviceOwnerPackageName(), DEVICE_OWNER_PROTECTED_PACKAGES); - } - - { - final OwnersTestable owners = new OwnersTestable(getServices()); - owners.load(); - - assertThat(owners.hasDeviceOwner()).isTrue(); - assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo( - DEVICE_OWNER_TYPE_FINANCED); - assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName())) - .isEqualTo(DEVICE_OWNER_PROTECTED_PACKAGES); - - assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isTrue(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse(); - - owners.setProfileOwnerUserRestrictionsMigrated(11); - - owners.setDeviceOwnerType(owners.getDeviceOwnerPackageName(), - DEVICE_OWNER_TYPE_DEFAULT, /* isAdminTestOnly= */ false); - // The previous device owner type should persist. - assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo( - DEVICE_OWNER_TYPE_FINANCED); - - owners.setDeviceOwnerProtectedPackages( - owners.getDeviceOwnerPackageName(), new ArrayList<>()); - assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName())) - .isEmpty(); - verify(getServices().packageManagerInternal) - .setDeviceOwnerProtectedPackages( - owners.getDeviceOwnerPackageName(), new ArrayList<>()); - } - - { - final OwnersTestable owners = new OwnersTestable(getServices()); - owners.load(); - - assertThat(owners.hasDeviceOwner()).isTrue(); - assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo( - DEVICE_OWNER_TYPE_FINANCED); - assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName())) - .isEmpty(); - - assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse(); - - owners.setProfileOwnerUserRestrictionsMigrated(11); - } - } - - @Test - public void testUpgrade05() throws Exception { - getServices().addUsers(10, 11, 20, 21); - - // First, migrate. - { - final OwnersTestable owners = new OwnersTestable(getServices()); - - DpmTestUtils.writeToFile(owners.getLegacyConfigFile(), - DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/test05/input.xml")); - - owners.load(); - - // The legacy file should be removed. - assertThat(owners.getLegacyConfigFile().exists()).isFalse(); - - // Note device initializer is no longer supported. No need to write the DO file. - assertThat(owners.getDeviceOwnerFile().exists()).isFalse(); - - assertThat(owners.getProfileOwnerFile(10).exists()).isFalse(); - assertThat(owners.getProfileOwnerFile(11).exists()).isFalse(); - assertThat(owners.getProfileOwnerFile(20).exists()).isFalse(); + public void loadProfileOwner() throws Exception { + getServices().addUsers(10); - assertThat(owners.hasDeviceOwner()).isFalse(); - assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL); - assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo( - DEVICE_OWNER_TYPE_DEFAULT); - assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName())) - .isEmpty(); - - - assertThat(owners.getSystemUpdatePolicy()).isNull(); - assertThat(owners.getProfileOwnerKeys()).isEmpty(); - - assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse(); - } - - // Then re-read and check. - { - final OwnersTestable owners = new OwnersTestable(getServices()); - owners.load(); + final OwnersTestable owners = new OwnersTestable(getServices()); - assertThat(owners.hasDeviceOwner()).isFalse(); - assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL); - assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo( - DEVICE_OWNER_TYPE_DEFAULT); - assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName())) - .isEmpty(); + DpmTestUtils.writeToFile(owners.getProfileOwnerFile(10), + DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/profile_owner_1.xml")); + owners.load(); - assertThat(owners.getSystemUpdatePolicy()).isNull(); - assertThat(owners.getProfileOwnerKeys()).isEmpty(); + assertThat(owners.hasDeviceOwner()).isFalse(); + assertThat(owners.getSystemUpdatePolicy()).isNull(); - assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse(); - } + assertThat(owners.getProfileOwnerKeys()).hasSize(1); + assertThat(owners.getProfileOwnerComponent(10)) + .isEqualTo(new ComponentName(TESTDPC_PACKAGE, + "com.afwsamples.testdpc.DeviceAdminReceiver")); } @Test - public void testUpgrade06() throws Exception { - getServices().addUsers(10, 11, 20, 21); - - // First, migrate. - { - final OwnersTestable owners = new OwnersTestable(getServices()); - - DpmTestUtils.writeToFile(owners.getLegacyConfigFile(), - DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/test06/input.xml")); - - owners.load(); - - // The legacy file should be removed. - assertThat(owners.getLegacyConfigFile().exists()).isFalse(); - - assertThat(owners.getDeviceOwnerFile().exists()).isTrue(); - - assertThat(owners.getProfileOwnerFile(10).exists()).isFalse(); - assertThat(owners.getProfileOwnerFile(11).exists()).isFalse(); - assertThat(owners.getProfileOwnerFile(20).exists()).isFalse(); - - assertThat(owners.hasDeviceOwner()).isFalse(); - assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL); - assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo( - DEVICE_OWNER_TYPE_DEFAULT); - assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName())) - .isEmpty(); - assertThat(owners.getProfileOwnerKeys()).isEmpty(); - - assertThat(owners.getSystemUpdatePolicy()).isNotNull(); - assertThat(owners.getSystemUpdatePolicy().getPolicyType()).isEqualTo(5); + public void loadDeviceOwner() throws Exception { + final OwnersTestable owners = new OwnersTestable(getServices()); - assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse(); - } + DpmTestUtils.writeToFile(owners.getDeviceOwnerFile(), + DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/device_owner_1.xml")); - // Then re-read and check. - { - final OwnersTestable owners = new OwnersTestable(getServices()); - owners.load(); + owners.load(); - assertThat(owners.hasDeviceOwner()).isFalse(); - assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL); - assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo( - DEVICE_OWNER_TYPE_DEFAULT); - assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName())) - .isEmpty(); - assertThat(owners.getProfileOwnerKeys()).isEmpty(); + assertThat(owners.hasDeviceOwner()).isTrue(); - assertThat(owners.getSystemUpdatePolicy()).isNotNull(); - assertThat(owners.getSystemUpdatePolicy().getPolicyType()).isEqualTo(5); + assertThat(owners.getProfileOwnerKeys()).hasSize(0); + assertThat(owners.getDeviceOwnerComponent()) + .isEqualTo(new ComponentName(TESTDPC_PACKAGE, + "com.afwsamples.testdpc.DeviceAdminReceiver")); - assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse(); - assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse(); - } + assertThat(owners.getSystemUpdatePolicy().getPolicyType()).isEqualTo(TYPE_INSTALL_WINDOWED); } @Test - public void testRemoveExistingFiles() throws Exception { - getServices().addUsers(10, 11, 20, 21); - + public void testDeviceOwnerType() throws Exception { final OwnersTestable owners = new OwnersTestable(getServices()); - // First, migrate to create new-style config files. - DpmTestUtils.writeToFile(owners.getLegacyConfigFile(), - DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/test04/input.xml")); + DpmTestUtils.writeToFile(owners.getDeviceOwnerFile(), + DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/device_owner_1.xml")); owners.load(); - assertThat(owners.getLegacyConfigFile().exists()).isFalse(); - - assertThat(owners.getDeviceOwnerFile().exists()).isTrue(); - assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo( - DEVICE_OWNER_TYPE_DEFAULT); - assertThat(owners.getDeviceOwnerProtectedPackages(owners.getDeviceOwnerPackageName())) - .isEmpty(); - assertThat(owners.getProfileOwnerFile(10).exists()).isTrue(); - assertThat(owners.getProfileOwnerFile(11).exists()).isTrue(); - - String previousDeviceOwnerPackageName = owners.getDeviceOwnerPackageName(); - owners.setDeviceOwnerType(previousDeviceOwnerPackageName, DEVICE_OWNER_TYPE_FINANCED, - /* isAdminTestOnly= */ false); - assertThat(owners.getDeviceOwnerType(previousDeviceOwnerPackageName)).isEqualTo( - DEVICE_OWNER_TYPE_FINANCED); - owners.setDeviceOwnerProtectedPackages( - previousDeviceOwnerPackageName, DEVICE_OWNER_PROTECTED_PACKAGES); - assertThat(owners.getDeviceOwnerProtectedPackages(previousDeviceOwnerPackageName)) - .isEqualTo(DEVICE_OWNER_PROTECTED_PACKAGES); - verify(getServices().packageManagerInternal) - .setDeviceOwnerProtectedPackages( - owners.getDeviceOwnerPackageName(), DEVICE_OWNER_PROTECTED_PACKAGES); - - // Then clear all information and save. - owners.clearDeviceOwner(); - owners.clearSystemUpdatePolicy(); - owners.removeProfileOwner(10); - owners.removeProfileOwner(11); - - owners.writeDeviceOwner(); - owners.writeProfileOwner(10); - owners.writeProfileOwner(11); - owners.writeProfileOwner(20); - owners.writeProfileOwner(21); + assertThat(owners.getDeviceOwnerType(TESTDPC_PACKAGE)) + .isEqualTo(DEVICE_OWNER_TYPE_DEFAULT); - // Now all files should be removed. - assertThat(owners.getDeviceOwnerFile().exists()).isFalse(); - assertThat(owners.getProfileOwnerFile(10).exists()).isFalse(); - assertThat(owners.getProfileOwnerFile(11).exists()).isFalse(); + // Should be able to set DO type to "financed". + owners.setDeviceOwnerType( + TESTDPC_PACKAGE, DEVICE_OWNER_TYPE_FINANCED, /* isAdminTestOnly= */ false); + assertThat(owners.getDeviceOwnerType(TESTDPC_PACKAGE)) + .isEqualTo(DEVICE_OWNER_TYPE_FINANCED); - assertThat(owners.getDeviceOwnerType(previousDeviceOwnerPackageName)).isEqualTo( - DEVICE_OWNER_TYPE_DEFAULT); - assertThat(owners.getDeviceOwnerProtectedPackages(previousDeviceOwnerPackageName)) - .isEmpty(); - verify(getServices().packageManagerInternal) - .setDeviceOwnerProtectedPackages( - previousDeviceOwnerPackageName, new ArrayList<>()); + // Once set, DO type cannot be changed. + owners.setDeviceOwnerType( + TESTDPC_PACKAGE, DEVICE_OWNER_TYPE_DEFAULT, /* isAdminTestOnly= */ false); + assertThat(owners.getDeviceOwnerType(TESTDPC_PACKAGE)) + .isEqualTo(DEVICE_OWNER_TYPE_FINANCED); } } diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterImplTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterImplTest.java index d8f4349b95bf..3be2aacc75cb 100644 --- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterImplTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterImplTest.java @@ -30,7 +30,6 @@ import android.annotation.Nullable; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManagerInternal; import android.content.pm.Signature; import android.content.pm.SigningDetails; import android.content.pm.UserInfo; @@ -48,7 +47,6 @@ import com.android.server.om.OverlayReferenceMapper; import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.pm.parsing.pkg.PackageImpl; import com.android.server.pm.parsing.pkg.ParsedPackage; -import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.pkg.component.ParsedActivity; import com.android.server.pm.pkg.component.ParsedActivityImpl; import com.android.server.pm.pkg.component.ParsedInstrumentationImpl; @@ -69,6 +67,7 @@ import org.mockito.stubbing.Answer; import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; @@ -103,10 +102,9 @@ public class AppsFilterImplTest { AppsFilterImpl.StateProvider mStateProvider; @Mock Executor mMockExecutor; - @Mock - PackageManagerInternal mMockPmInternal; private ArrayMap<String, PackageSetting> mExisting = new ArrayMap<>(); + private Collection<SharedUserSetting> mSharedUserSettings = new ArraySet<>(); private static ParsingPackage pkg(String packageName) { return PackageImpl.forTesting(packageName) @@ -205,7 +203,7 @@ public class AppsFilterImplTest { MockitoAnnotations.initMocks(this); doAnswer(invocation -> { ((AppsFilterImpl.StateProvider.CurrentStateCallback) invocation.getArgument(0)) - .currentState(mExisting, USER_INFO_LIST); + .currentState(mExisting, mSharedUserSettings, USER_INFO_LIST); return new Object(); }).when(mStateProvider) .runWithState(any(AppsFilterImpl.StateProvider.CurrentStateCallback.class)); @@ -226,7 +224,7 @@ public class AppsFilterImplTest { public void testSystemReadyPropogates() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); final WatchableTester watcher = new WatchableTester(appsFilter, "onChange"); watcher.register(); appsFilter.onSystemReady(); @@ -238,7 +236,7 @@ public class AppsFilterImplTest { public void testQueriesAction_FilterMatches() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); final WatchableTester watcher = new WatchableTester(appsFilter, "onChange"); watcher.register(); simulateAddBasicAndroid(appsFilter); @@ -261,7 +259,7 @@ public class AppsFilterImplTest { public void testQueriesProtectedAction_FilterDoesNotMatch() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); final WatchableTester watcher = new WatchableTester(appsFilter, "onChange"); watcher.register(); final Signature frameworkSignature = Mockito.mock(Signature.class); @@ -310,7 +308,7 @@ public class AppsFilterImplTest { public void testQueriesProvider_FilterMatches() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); final WatchableTester watcher = new WatchableTester(appsFilter, "onChange"); watcher.register(); simulateAddBasicAndroid(appsFilter); @@ -335,7 +333,7 @@ public class AppsFilterImplTest { public void testOnUserUpdated_FilterMatches() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -357,7 +355,7 @@ public class AppsFilterImplTest { // adds new user doAnswer(invocation -> { ((AppsFilterImpl.StateProvider.CurrentStateCallback) invocation.getArgument(0)) - .currentState(mExisting, USER_INFO_LIST_WITH_ADDED); + .currentState(mExisting, mSharedUserSettings, USER_INFO_LIST_WITH_ADDED); return new Object(); }).when(mStateProvider) .runWithState(any(AppsFilterImpl.StateProvider.CurrentStateCallback.class)); @@ -374,7 +372,7 @@ public class AppsFilterImplTest { // delete user doAnswer(invocation -> { ((AppsFilterImpl.StateProvider.CurrentStateCallback) invocation.getArgument(0)) - .currentState(mExisting, USER_INFO_LIST); + .currentState(mExisting, mSharedUserSettings, USER_INFO_LIST); return new Object(); }).when(mStateProvider) .runWithState(any(AppsFilterImpl.StateProvider.CurrentStateCallback.class)); @@ -393,7 +391,7 @@ public class AppsFilterImplTest { public void testQueriesDifferentProvider_Filters() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); final WatchableTester watcher = new WatchableTester(appsFilter, "onChange"); watcher.register(); simulateAddBasicAndroid(appsFilter); @@ -418,7 +416,7 @@ public class AppsFilterImplTest { public void testQueriesProviderWithSemiColon_FilterMatches() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -437,7 +435,7 @@ public class AppsFilterImplTest { public void testQueriesAction_NoMatchingAction_Filters() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -454,7 +452,7 @@ public class AppsFilterImplTest { public void testQueriesAction_NoMatchingActionFilterLowSdk_DoesntFilter() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -475,7 +473,7 @@ public class AppsFilterImplTest { public void testNoQueries_Filters() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -492,7 +490,7 @@ public class AppsFilterImplTest { public void testNoUsesLibrary_Filters() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, /* systemAppsQueryable */ false, /* overlayProvider */ null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -518,7 +516,7 @@ public class AppsFilterImplTest { public void testUsesLibrary_DoesntFilter() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, /* systemAppsQueryable */ false, /* overlayProvider */ null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -545,7 +543,7 @@ public class AppsFilterImplTest { public void testUsesOptionalLibrary_DoesntFilter() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, /* systemAppsQueryable */ false, /* overlayProvider */ null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -572,7 +570,7 @@ public class AppsFilterImplTest { public void testUsesLibrary_ShareUid_DoesntFilter() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, /* systemAppsQueryable */ false, /* overlayProvider */ null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -604,7 +602,7 @@ public class AppsFilterImplTest { public void testForceQueryable_SystemDoesntFilter() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -623,7 +621,7 @@ public class AppsFilterImplTest { public void testForceQueryable_NonSystemFilters() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -641,7 +639,7 @@ public class AppsFilterImplTest { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{"com.some.package"}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -660,7 +658,7 @@ public class AppsFilterImplTest { public void testSystemSignedTarget_DoesntFilter() throws CertificateException { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); appsFilter.onSystemReady(); final Signature frameworkSignature = Mockito.mock(Signature.class); @@ -690,7 +688,7 @@ public class AppsFilterImplTest { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{"com.some.package"}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -708,8 +706,7 @@ public class AppsFilterImplTest { public void testSystemQueryable_DoesntFilter() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, - true /* system force queryable */, null, mMockExecutor, - mMockPmInternal); + true /* system force queryable */, null, mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -727,7 +724,7 @@ public class AppsFilterImplTest { public void testQueriesPackage_DoesntFilter() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -746,7 +743,7 @@ public class AppsFilterImplTest { .thenReturn(false); final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -763,7 +760,7 @@ public class AppsFilterImplTest { public void testSystemUid_DoesntFilter() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -779,7 +776,7 @@ public class AppsFilterImplTest { public void testSystemUidSecondaryUser_DoesntFilter() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -796,7 +793,7 @@ public class AppsFilterImplTest { public void testNonSystemUid_NoCallingSetting_Filters() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -811,7 +808,7 @@ public class AppsFilterImplTest { public void testNoTargetPackage_filters() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -869,7 +866,7 @@ public class AppsFilterImplTest { return Collections.emptyMap(); } }, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -925,16 +922,11 @@ public class AppsFilterImplTest { .setOverlayTargetOverlayableName("overlayableName"); ParsingPackage actorOne = pkg("com.some.package.actor.one"); ParsingPackage actorTwo = pkg("com.some.package.actor.two"); - ArraySet<PackageStateInternal> actorSharedSettingPackages = new ArraySet<>(); PackageSetting ps1 = getPackageSettingFromParsingPackage(actorOne, DUMMY_ACTOR_APPID, null /*settingBuilder*/); PackageSetting ps2 = getPackageSettingFromParsingPackage(actorTwo, DUMMY_ACTOR_APPID, null /*settingBuilder*/); - actorSharedSettingPackages.add(ps1); - actorSharedSettingPackages.add(ps2); - when(mMockPmInternal.getSharedUserPackages(any(Integer.class))).thenReturn( - actorSharedSettingPackages - ); + final AppsFilterImpl appsFilter = new AppsFilterImpl( mStateProvider, mFeatureConfigMock, @@ -965,7 +957,7 @@ public class AppsFilterImplTest { return Collections.emptyMap(); } }, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -989,7 +981,7 @@ public class AppsFilterImplTest { public void testInitiatingApp_DoesntFilter() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -1007,7 +999,7 @@ public class AppsFilterImplTest { public void testUninstalledInitiatingApp_Filters() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -1025,7 +1017,7 @@ public class AppsFilterImplTest { public void testOriginatingApp_Filters() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); final WatchableTester watcher = new WatchableTester(appsFilter, "onChange"); watcher.register(); simulateAddBasicAndroid(appsFilter); @@ -1050,7 +1042,7 @@ public class AppsFilterImplTest { public void testInstallingApp_DoesntFilter() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); final WatchableTester watcher = new WatchableTester(appsFilter, "onChange"); watcher.register(); simulateAddBasicAndroid(appsFilter); @@ -1075,7 +1067,7 @@ public class AppsFilterImplTest { public void testInstrumentation_DoesntFilter() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); final WatchableTester watcher = new WatchableTester(appsFilter, "onChange"); watcher.register(); simulateAddBasicAndroid(appsFilter); @@ -1104,7 +1096,7 @@ public class AppsFilterImplTest { public void testWhoCanSee() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); final WatchableTester watcher = new WatchableTester(appsFilter, "onChange"); watcher.register(); simulateAddBasicAndroid(appsFilter); @@ -1177,7 +1169,7 @@ public class AppsFilterImplTest { public void testOnChangeReport() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); final WatchableTester watcher = new WatchableTester(appsFilter, "onChange"); watcher.register(); simulateAddBasicAndroid(appsFilter); @@ -1250,7 +1242,7 @@ public class AppsFilterImplTest { public void testOnChangeReportedFilter() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); final WatchableTester watcher = new WatchableTester(appsFilter, "onChange filter"); @@ -1276,7 +1268,7 @@ public class AppsFilterImplTest { public void testAppsFilterRead() throws Exception { final AppsFilterImpl appsFilter = new AppsFilterImpl(mStateProvider, mFeatureConfigMock, new String[]{}, false, null, - mMockExecutor, mMockPmInternal); + mMockExecutor); simulateAddBasicAndroid(appsFilter); appsFilter.onSystemReady(); @@ -1379,6 +1371,7 @@ public class AppsFilterImplTest { if (sharedUserSetting != null) { sharedUserSetting.addPackage(setting); setting.setSharedUserAppId(sharedUserSetting.mAppId); + mSharedUserSettings.add(sharedUserSetting); } filter.addPackage(setting); } diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java index a79a52c1c198..e4ee4d064724 100644 --- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java @@ -538,6 +538,11 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { } @Override + ComponentName injectChooserActivity() { + return mInjectedChooserActivity; + } + + @Override void wtf(String message, Throwable th) { // During tests, WTF is fatal. fail(message + " exception: " + th + "\n" + Log.getStackTraceString(th)); @@ -678,6 +683,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { protected int mInjectedCallingUid; protected String mInjectedClientPackage; + protected ComponentName mInjectedChooserActivity; protected Map<String, PackageInfo> mInjectedPackages; @@ -723,6 +729,9 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { protected static final String LAUNCHER_4 = "com.android.launcher.4"; protected static final int LAUNCHER_UID_4 = 10014; + protected static final String CHOOSER_ACTIVITY_PACKAGE = "com.android.intentresolver"; + protected static final int CHOOSER_ACTIVITY_UID = 10015; + protected static final int USER_0 = UserHandle.USER_SYSTEM; protected static final int USER_10 = 10; protected static final int USER_11 = 11; diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java index a350dfbad662..867890f938ba 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java @@ -6901,6 +6901,9 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { } public void testGetShareTargets_permission() { + addPackage(CHOOSER_ACTIVITY_PACKAGE, CHOOSER_ACTIVITY_UID, 10, "sig1"); + mInjectedChooserActivity = + ComponentName.createRelative(CHOOSER_ACTIVITY_PACKAGE, ".ChooserActivity"); IntentFilter filter = new IntentFilter(); assertExpectException(SecurityException.class, "Missing permission", () -> @@ -6909,6 +6912,11 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { // Has permission, now it should pass. mCallerPermissions.add(permission.MANAGE_APP_PREDICTIONS); mManager.getShareTargets(filter); + + runWithCaller(CHOOSER_ACTIVITY_PACKAGE, USER_0, () -> { + // Access is allowed when called from the configured system ChooserActivity + mManager.getShareTargets(filter); + }); } public void testHasShareTargets_permission() { diff --git a/services/tests/servicestests/src/com/android/server/policy/SideFpsEventHandlerTest.java b/services/tests/servicestests/src/com/android/server/policy/SideFpsEventHandlerTest.java index 41c7e31147a5..371861f74871 100644 --- a/services/tests/servicestests/src/com/android/server/policy/SideFpsEventHandlerTest.java +++ b/services/tests/servicestests/src/com/android/server/policy/SideFpsEventHandlerTest.java @@ -26,9 +26,9 @@ import static org.mockito.Mockito.when; import android.app.AlertDialog; import android.content.pm.PackageManager; +import android.hardware.biometrics.BiometricStateListener; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; -import android.hardware.fingerprint.FingerprintStateListener; import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback; import android.os.Handler; import android.os.PowerManager; @@ -61,11 +61,11 @@ import java.util.List; public class SideFpsEventHandlerTest { private static final List<Integer> sAllStates = List.of( - FingerprintStateListener.STATE_IDLE, - FingerprintStateListener.STATE_ENROLLING, - FingerprintStateListener.STATE_KEYGUARD_AUTH, - FingerprintStateListener.STATE_BP_AUTH, - FingerprintStateListener.STATE_AUTH_OTHER); + BiometricStateListener.STATE_IDLE, + BiometricStateListener.STATE_ENROLLING, + BiometricStateListener.STATE_KEYGUARD_AUTH, + BiometricStateListener.STATE_BP_AUTH, + BiometricStateListener.STATE_AUTH_OTHER); @Rule public TestableContext mContext = @@ -83,7 +83,7 @@ public class SideFpsEventHandlerTest { private TestLooper mLooper = new TestLooper(); private SideFpsEventHandler mEventHandler; - private FingerprintStateListener mFingerprintStateListener; + private BiometricStateListener mBiometricStateListener; @Before public void setup() { @@ -116,7 +116,7 @@ public class SideFpsEventHandlerTest { setupWithSensor(false /* hasSfps */, true /* initialized */); for (int state : sAllStates) { - setFingerprintState(state); + setBiometricState(state); assertThat(mEventHandler.onSinglePressDetected(200L)).isFalse(); mLooper.dispatchAll(); @@ -129,7 +129,7 @@ public class SideFpsEventHandlerTest { setupWithSensor(true /* hasSfps */, false /* initialized */); for (int state : sAllStates) { - setFingerprintState(state); + setBiometricState(state); assertThat(mEventHandler.onSinglePressDetected(400L)).isFalse(); mLooper.dispatchAll(); @@ -141,10 +141,10 @@ public class SideFpsEventHandlerTest { public void ignoresWhenIdleOrUnknown() throws Exception { setupWithSensor(true /* hasSfps */, true /* initialized */); - setFingerprintState(FingerprintStateListener.STATE_IDLE); + setBiometricState(BiometricStateListener.STATE_IDLE); assertThat(mEventHandler.onSinglePressDetected(80000L)).isFalse(); - setFingerprintState(FingerprintStateListener.STATE_AUTH_OTHER); + setBiometricState(BiometricStateListener.STATE_AUTH_OTHER); assertThat(mEventHandler.onSinglePressDetected(90000L)).isFalse(); mLooper.dispatchAll(); @@ -155,7 +155,7 @@ public class SideFpsEventHandlerTest { public void ignoresOnKeyguard() throws Exception { setupWithSensor(true /* hasSfps */, true /* initialized */); - setFingerprintState(FingerprintStateListener.STATE_KEYGUARD_AUTH); + setBiometricState(BiometricStateListener.STATE_KEYGUARD_AUTH); assertThat(mEventHandler.onSinglePressDetected(80000L)).isFalse(); mLooper.dispatchAll(); @@ -166,7 +166,7 @@ public class SideFpsEventHandlerTest { public void promptsWhenBPisActive() throws Exception { setupWithSensor(true /* hasSfps */, true /* initialized */); - setFingerprintState(FingerprintStateListener.STATE_BP_AUTH); + setBiometricState(BiometricStateListener.STATE_BP_AUTH); assertThat(mEventHandler.onSinglePressDetected(80000L)).isTrue(); mLooper.dispatchAll(); @@ -177,16 +177,16 @@ public class SideFpsEventHandlerTest { public void promptsWhenEnrolling() throws Exception { setupWithSensor(true /* hasSfps */, true /* initialized */); - setFingerprintState(FingerprintStateListener.STATE_ENROLLING); + setBiometricState(BiometricStateListener.STATE_ENROLLING); assertThat(mEventHandler.onSinglePressDetected(80000L)).isTrue(); mLooper.dispatchAll(); verify(mAlertDialog).show(); } - private void setFingerprintState(@FingerprintStateListener.State int newState) { - if (mFingerprintStateListener != null) { - mFingerprintStateListener.onStateChanged(newState); + private void setBiometricState(@BiometricStateListener.State int newState) { + if (mBiometricStateListener != null) { + mBiometricStateListener.onStateChanged(newState); mLooper.dispatchAll(); } } @@ -204,10 +204,10 @@ public class SideFpsEventHandlerTest { fpCallbackCaptor.getValue().onAllAuthenticatorsRegistered( List.of(mock(FingerprintSensorPropertiesInternal.class))); if (hasSfps) { - ArgumentCaptor<FingerprintStateListener> captor = ArgumentCaptor.forClass( - FingerprintStateListener.class); - verify(mFingerprintManager).registerFingerprintStateListener(captor.capture()); - mFingerprintStateListener = captor.getValue(); + ArgumentCaptor<BiometricStateListener> captor = ArgumentCaptor.forClass( + BiometricStateListener.class); + verify(mFingerprintManager).registerBiometricStateListener(captor.capture()); + mBiometricStateListener = captor.getValue(); } } } diff --git a/services/tests/servicestests/src/com/android/server/power/NotifierTest.java b/services/tests/servicestests/src/com/android/server/power/NotifierTest.java index a3223d6d2b7b..8f5f0e6fe131 100644 --- a/services/tests/servicestests/src/com/android/server/power/NotifierTest.java +++ b/services/tests/servicestests/src/com/android/server/power/NotifierTest.java @@ -16,6 +16,8 @@ package com.android.server.power; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; @@ -56,6 +58,8 @@ import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.concurrent.Executor; + /** * Tests for {@link com.android.server.power.Notifier} */ @@ -79,6 +83,7 @@ public class NotifierTest { private Context mContextSpy; private Resources mResourcesSpy; private TestLooper mTestLooper = new TestLooper(); + private FakeExecutor mTestExecutor = new FakeExecutor(); private Notifier mNotifier; @Before @@ -107,6 +112,7 @@ public class NotifierTest { // WHEN wired charging starts mNotifier.onWiredChargingStarted(USER_ID); mTestLooper.dispatchAll(); + mTestExecutor.simulateAsyncExecutionOfLastCommand(); // THEN the device vibrates once verify(mVibrator, times(1)).vibrate(any(), any(VibrationAttributes.class)); @@ -122,6 +128,7 @@ public class NotifierTest { // WHEN wired charging starts mNotifier.onWiredChargingStarted(USER_ID); mTestLooper.dispatchAll(); + mTestExecutor.simulateAsyncExecutionOfLastCommand(); // THEN the device doesn't vibrate verify(mVibrator, never()).vibrate(any(), any(VibrationAttributes.class)); @@ -137,6 +144,7 @@ public class NotifierTest { // WHEN wireless charging starts mNotifier.onWirelessChargingStarted(5, USER_ID); mTestLooper.dispatchAll(); + mTestExecutor.simulateAsyncExecutionOfLastCommand(); // THEN the device vibrates once verify(mVibrator, times(1)).vibrate(any(), any(VibrationAttributes.class)); @@ -152,6 +160,7 @@ public class NotifierTest { // WHEN wireless charging starts mNotifier.onWirelessChargingStarted(5, USER_ID); mTestLooper.dispatchAll(); + mTestExecutor.simulateAsyncExecutionOfLastCommand(); // THEN the device doesn't vibrate verify(mVibrator, never()).vibrate(any(), any(VibrationAttributes.class)); @@ -170,6 +179,7 @@ public class NotifierTest { // WHEN wired charging starts mNotifier.onWiredChargingStarted(USER_ID); mTestLooper.dispatchAll(); + mTestExecutor.simulateAsyncExecutionOfLastCommand(); // THEN the device doesn't vibrate verify(mVibrator, never()).vibrate(any(), any(VibrationAttributes.class)); @@ -186,6 +196,7 @@ public class NotifierTest { // WHEN wireless charging starts mNotifier.onWirelessChargingStarted(5, USER_ID); mTestLooper.dispatchAll(); + mTestExecutor.simulateAsyncExecutionOfLastCommand(); // THEN the charging animation is triggered verify(mStatusBarManagerInternal, times(1)).showChargingAnimation(5); @@ -202,6 +213,7 @@ public class NotifierTest { // WHEN wireless charging starts mNotifier.onWirelessChargingStarted(5, USER_ID); mTestLooper.dispatchAll(); + mTestExecutor.simulateAsyncExecutionOfLastCommand(); // THEN the charging animation never gets called verify(mStatusBarManagerInternal, never()).showChargingAnimation(anyInt()); @@ -211,7 +223,8 @@ public class NotifierTest { @Override Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats, SuspendBlocker suspendBlocker, WindowManagerPolicy policy, - FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector) { + FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector, + Executor backgroundExecutor) { return mNotifierMock; } @@ -300,6 +313,32 @@ public class NotifierTest { mInjector.createSuspendBlocker(mService, "testBlocker"), null, null, - null); + null, + mTestExecutor); + } + + private static class FakeExecutor implements Executor { + private Runnable mLastCommand; + + @Override + public void execute(Runnable command) { + assertNull(mLastCommand); + assertNotNull(command); + mLastCommand = command; + } + + public Runnable getAndResetLastCommand() { + Runnable toReturn = mLastCommand; + mLastCommand = null; + return toReturn; + } + + public void simulateAsyncExecutionOfLastCommand() { + Runnable toRun = getAndResetLastCommand(); + if (toRun != null) { + toRun.run(); + } + } } + } diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java index 3e81d601e477..fbcad62988be 100644 --- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java @@ -87,7 +87,6 @@ import com.android.server.lights.LightsManager; import com.android.server.policy.WindowManagerPolicy; import com.android.server.power.PowerManagerService.BatteryReceiver; import com.android.server.power.PowerManagerService.BinderService; -import com.android.server.power.PowerManagerService.DockReceiver; import com.android.server.power.PowerManagerService.Injector; import com.android.server.power.PowerManagerService.NativeWrapper; import com.android.server.power.PowerManagerService.UserSwitchedReceiver; @@ -110,6 +109,7 @@ import org.mockito.stubbing.Answer; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicReference; /** @@ -151,7 +151,6 @@ public class PowerManagerServiceTest { private Resources mResourcesSpy; private OffsettableClock mClock; private TestLooper mTestLooper; - private DockReceiver mDockReceiver; private static class IntentFilterMatcher implements ArgumentMatcher<IntentFilter> { private final IntentFilter mFilter; @@ -222,7 +221,8 @@ public class PowerManagerServiceTest { @Override Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats, SuspendBlocker suspendBlocker, WindowManagerPolicy policy, - FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector) { + FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector, + Executor executor) { return mNotifierMock; } @@ -338,14 +338,6 @@ public class PowerManagerServiceTest { argThat(new IntentFilterMatcher(usFilter)), isNull(), isA(Handler.class)); mUserSwitchedReceiver = userSwitchedCaptor.getValue(); - // Grab the DockReceiver - ArgumentCaptor<DockReceiver> dockReceiverCaptor = - ArgumentCaptor.forClass(DockReceiver.class); - IntentFilter dockFilter = new IntentFilter(Intent.ACTION_DOCK_EVENT); - verify(mContextSpy).registerReceiver(dockReceiverCaptor.capture(), - argThat(new IntentFilterMatcher(dockFilter)), isNull(), isA(Handler.class)); - mDockReceiver = dockReceiverCaptor.getValue(); - mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED); } @@ -394,16 +386,6 @@ public class PowerManagerServiceTest { .thenReturn(minimumScreenOffTimeoutConfigMillis); } - private void setScreenOffTimeout(int screenOffTimeoutMillis) { - Settings.System.putInt(mContextSpy.getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, - screenOffTimeoutMillis); - } - - private void setScreenOffTimeoutDocked(int screenOffTimeoutMillis) { - Settings.System.putInt(mContextSpy.getContentResolver(), - Settings.System.SCREEN_OFF_TIMEOUT_DOCKED, screenOffTimeoutMillis); - } - private void advanceTime(long timeMs) { mClock.fastForward(timeMs); mTestLooper.dispatchAll(); @@ -952,71 +934,6 @@ public class PowerManagerServiceTest { } @Test - public void testScreenOffTimeout_goesToSleepAfterTimeout() { - final DisplayInfo info = new DisplayInfo(); - info.displayGroupId = Display.DEFAULT_DISPLAY_GROUP; - when(mDisplayManagerInternalMock.getDisplayInfo(Display.DEFAULT_DISPLAY)).thenReturn(info); - - setMinimumScreenOffTimeoutConfig(10); - setScreenOffTimeout(10); - - createService(); - startSystem(); - - mService.getBinderServiceInstance().userActivity(Display.DEFAULT_DISPLAY, mClock.now(), - PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0); - assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); - advanceTime(15); - assertThat(mService.getGlobalWakefulnessLocked()).isNotEqualTo(WAKEFULNESS_AWAKE); - } - - @Test - public void testScreenOffTimeout_usesRegularTimeoutWhenNotDocked() { - final DisplayInfo info = new DisplayInfo(); - info.displayGroupId = Display.DEFAULT_DISPLAY_GROUP; - when(mDisplayManagerInternalMock.getDisplayInfo(Display.DEFAULT_DISPLAY)).thenReturn(info); - - setMinimumScreenOffTimeoutConfig(10); - setScreenOffTimeout(10); - setScreenOffTimeoutDocked(30); - - createService(); - startSystem(); - - mService.getBinderServiceInstance().userActivity(Display.DEFAULT_DISPLAY, mClock.now(), - PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0); - assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); - advanceTime(15); - assertThat(mService.getGlobalWakefulnessLocked()).isNotEqualTo(WAKEFULNESS_AWAKE); - } - - @Test - public void testScreenOffTimeout_usesDockedTimeoutWhenDocked() { - final DisplayInfo info = new DisplayInfo(); - info.displayGroupId = Display.DEFAULT_DISPLAY_GROUP; - when(mDisplayManagerInternalMock.getDisplayInfo(Display.DEFAULT_DISPLAY)).thenReturn(info); - - setMinimumScreenOffTimeoutConfig(10); - setScreenOffTimeout(10); - setScreenOffTimeoutDocked(30); - - createService(); - startSystem(); - - mService.getBinderServiceInstance().userActivity(Display.DEFAULT_DISPLAY, mClock.now(), - PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0); - mDockReceiver.onReceive(mContextSpy, - new Intent(Intent.ACTION_DOCK_EVENT).putExtra(Intent.EXTRA_DOCK_STATE, - Intent.EXTRA_DOCK_STATE_DESK)); - - assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); - advanceTime(15); - assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); - advanceTime(20); - assertThat(mService.getGlobalWakefulnessLocked()).isNotEqualTo(WAKEFULNESS_AWAKE); - } - - @Test public void testInattentiveSleep_goesToSleepWithWakeLock() { final String pkg = mContextSpy.getOpPackageName(); final Binder token = new Binder(); diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java b/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java index 2d0dca25465b..c9fc033e9086 100644 --- a/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java +++ b/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java @@ -61,6 +61,16 @@ class FakeTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy { } @Override + public boolean isTelephonyTimeZoneDetectionSupported() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isGeoTimeZoneDetectionSupported() { + throw new UnsupportedOperationException(); + } + + @Override public void dump(IndentingPrintWriter pw, String[] args) { mDumpCalled = true; } diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java index 0c28d8c761ab..0a50e790215f 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java @@ -193,7 +193,7 @@ public class VibrationSettingsTest { public void removeListener_noMoreCallbacksToListener() { mVibrationSettings.addListener(mListenerMock); - setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0); + setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, 0); verify(mListenerMock).onChange(); mVibrationSettings.removeListener(mListenerMock); @@ -291,8 +291,6 @@ public class VibrationSettingsTest { public void shouldIgnoreVibration_withRingerModeSilent_ignoresRingtoneAndNotification() { // Vibrating settings on are overruled by ringer mode. setUserSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED, 1); - setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1); - setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 1); setRingerMode(AudioManager.RINGER_MODE_SILENT); for (int usage : ALL_USAGES) { @@ -360,44 +358,25 @@ public class VibrationSettingsTest { assertVibrationNotIgnoredForUsage(usage); } } + @Test - public void shouldIgnoreVibration_withRingSettingsOff_disableRingtoneVibrations() { + public void shouldIgnoreVibration_withRingSettingsOff_allowsAllVibrations() { + // VIBRATE_WHEN_RINGING is deprecated and should have no effect on the ring vibration + // setting. The ramping ringer is also independent now, instead of a 3-state setting. setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0); setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0); for (int usage : ALL_USAGES) { - if (usage == USAGE_RINGTONE) { - assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_SETTINGS); - } else { - assertVibrationNotIgnoredForUsage(usage); - } + assertVibrationNotIgnoredForUsage(usage); assertVibrationNotIgnoredForUsageAndFlags(usage, VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF); } } @Test - public void shouldIgnoreVibration_withRingSettingsOn_allowsAllVibrations() { - setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1); - setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0); - - for (int usage : ALL_USAGES) { - assertVibrationNotIgnoredForUsage(usage); - } - } - - @Test - public void shouldIgnoreVibration_withRampingRingerOn_allowsAllVibrations() { - setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0); - setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 1); - - for (int usage : ALL_USAGES) { - assertVibrationNotIgnoredForUsage(usage); - } - } - - @Test public void shouldIgnoreVibration_withHapticFeedbackDisabled_ignoresTouchVibration() { + // HAPTIC_FEEDBACK_ENABLED is deprecated but it was the only setting used to disable touch + // feedback vibrations. Continue to apply this on top of the intensity setting. setUserSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED, 0); for (int usage : ALL_USAGES) { @@ -459,8 +438,6 @@ public class VibrationSettingsTest { @Test public void shouldIgnoreVibration_withRingSettingsOff_ignoresRingtoneVibrations() { // Vibrating settings on are overruled by ring intensity setting. - setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1); - setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 1); setRingerMode(AudioManager.RINGER_MODE_VIBRATE); setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF); @@ -479,7 +456,6 @@ public class VibrationSettingsTest { public void shouldIgnoreVibration_updateTriggeredAfterInternalRingerModeChanged() { // Vibrating settings on are overruled by ringer mode. setUserSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED, 1); - setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1); setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 1); setRingerMode(AudioManager.RINGER_MODE_NORMAL); diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java index 4fbf0065f78d..c735bb7add0a 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java @@ -559,30 +559,26 @@ public class VibratorManagerServiceTest { } @Test - public void vibrate_withRingtone_usesRingtoneSettings() throws Exception { + public void vibrate_withRingtone_usesRingerModeSettings() throws Exception { mockVibrators(1); FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1); fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_CLICK, VibrationEffect.EFFECT_HEAVY_CLICK, VibrationEffect.EFFECT_DOUBLE_CLICK); - setRingerMode(AudioManager.RINGER_MODE_NORMAL); - setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0); - setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0); + setRingerMode(AudioManager.RINGER_MODE_SILENT); VibratorManagerService service = createSystemReadyService(); vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), RINGTONE_ATTRS); // Wait before checking it never played. assertFalse(waitUntil(s -> !fakeVibrator.getAllEffectSegments().isEmpty(), service, /* timeout= */ 50)); - setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0); - setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 1); + setRingerMode(AudioManager.RINGER_MODE_NORMAL); service = createSystemReadyService(); vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK), RINGTONE_ATTRS); assertTrue(waitUntil(s -> fakeVibrator.getAllEffectSegments().size() == 1, service, TEST_TIMEOUT_MILLIS)); - setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1); - setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0); + setRingerMode(AudioManager.RINGER_MODE_VIBRATE); service = createSystemReadyService(); vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK), RINGTONE_ATTRS); assertTrue(waitUntil(s -> fakeVibrator.getAllEffectSegments().size() == 2, @@ -1225,7 +1221,6 @@ public class VibratorManagerServiceTest { mockVibrators(1); mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL); setRingerMode(AudioManager.RINGER_MODE_NORMAL); - setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1); createSystemReadyService(); IBinder firstToken = mock(IBinder.class); @@ -1296,21 +1291,17 @@ public class VibratorManagerServiceTest { ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME, audioAttrs, mock(IExternalVibrationController.class)); - setRingerMode(AudioManager.RINGER_MODE_NORMAL); - setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0); - setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0); + setRingerMode(AudioManager.RINGER_MODE_SILENT); createSystemReadyService(); int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration); assertEquals(IExternalVibratorService.SCALE_MUTE, scale); - setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0); - setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 1); + setRingerMode(AudioManager.RINGER_MODE_NORMAL); createSystemReadyService(); scale = mExternalVibratorService.onExternalVibrationStart(externalVibration); assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale); - setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1); - setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0); + setRingerMode(AudioManager.RINGER_MODE_VIBRATE); createSystemReadyService(); scale = mExternalVibratorService.onExternalVibrationStart(externalVibration); assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 1cf96972c225..b987c692bddb 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -170,6 +170,7 @@ import android.service.notification.NotificationListenerService; import android.service.notification.NotificationStats; import android.service.notification.StatusBarNotification; import android.service.notification.ZenPolicy; +import android.telecom.TelecomManager; import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; @@ -290,6 +291,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Mock ActivityManager mActivityManager; @Mock + TelecomManager mTelecomManager; + @Mock Resources mResources; @Mock RankingHandler mRankingHandler; @@ -494,7 +497,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mAppUsageStats, mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal, mAppOpsManager, mAppOpsService, mUm, mHistoryManager, mStatsManager, mock(TelephonyManager.class), - mAmi, mToastRateLimiter, mPermissionHelper, mock(UsageStatsManagerInternal.class)); + mAmi, mToastRateLimiter, mPermissionHelper, mock(UsageStatsManagerInternal.class), + mTelecomManager); // Return first true for RoleObserver main-thread check when(mMainLooper.isCurrentThread()).thenReturn(true).thenReturn(false); mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY, mMainLooper); @@ -9127,6 +9131,54 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testCallNotificationsBypassBlock() throws Exception { + when(mAmi.getPendingIntentFlags(any(IIntentSender.class))) + .thenReturn(FLAG_MUTABLE | FLAG_ONE_SHOT); + when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); + + Notification.Builder nb = new Notification.Builder( + mContext, mTestNotificationChannel.getId()) + .setContentTitle("foo") + .setSmallIcon(android.R.drawable.sym_def_app_icon) + .addAction(new Notification.Action.Builder(null, "test", null).build()); + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, + nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); + NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); + + mBinderService.setNotificationsEnabledForPackage( + r.getSbn().getPackageName(), r.getUid(), false); + + // normal blocked notifications - blocked + assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), + r.getSbn().getId(), r.getSbn().getTag(), r, false)).isFalse(); + + // just using the style - blocked + Person person = new Person.Builder() + .setName("caller") + .build(); + nb.setStyle(Notification.CallStyle.forOngoingCall( + person, mock(PendingIntent.class))); + nb.setFullScreenIntent(mock(PendingIntent.class), true); + sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, + nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); + r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); + + assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), + r.getSbn().getId(), r.getSbn().getTag(), r, false)).isFalse(); + + // style + managed call - bypasses block + when(mTelecomManager.isInManagedCall()).thenReturn(true); + assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), + r.getSbn().getId(), r.getSbn().getTag(), r, false)).isTrue(); + + // style + self managed call - bypasses block + when(mTelecomManager.isInSelfManagedCall( + r.getSbn().getPackageName(), r.getUser())).thenReturn(true); + assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), + r.getSbn().getId(), r.getSbn().getTag(), r, false)).isTrue(); + } + + @Test public void testGetAllUsersNotificationPermissions_migrationNotEnabled() { // make sure we don't bother if the migration is not enabled assertThat(mService.getAllUsersNotificationPermissions()).isNull(); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java index 0f6d5a56c667..b751c7fc73ea 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java @@ -97,6 +97,7 @@ import android.os.UserManager; import android.provider.Settings; import android.service.notification.NotificationListenerFilter; import android.service.notification.StatusBarNotification; +import android.telecom.TelecomManager; import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; @@ -379,7 +380,7 @@ public class NotificationPermissionMigrationTest extends UiServiceTestCase { mAppUsageStats, mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal, mAppOpsManager, mock(IAppOpsService.class), mUm, mHistoryManager, mStatsManager, mock(TelephonyManager.class), mAmi, mToastRateLimiter, mPermissionHelper, - mock(UsageStatsManagerInternal.class)); + mock(UsageStatsManagerInternal.class), mock(TelecomManager.class)); // Return first true for RoleObserver main-thread check when(mMainLooper.isCurrentThread()).thenReturn(true).thenReturn(false); mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY, mMainLooper); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java index 7e27e5438a0c..d89141cc1000 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java @@ -816,8 +816,10 @@ public class NotificationRecordTest extends UiServiceTestCase { when(ugm.checkGrantUriPermission(anyInt(), eq(null), any(Uri.class), anyInt(), anyInt())).thenThrow(new SecurityException()); - Notification n = mock(Notification.class); - when(n.getChannelId()).thenReturn(channel.getId()); + channel.setSound(null, null); + Notification n = new Notification.Builder(mContext, channel.getId()) + .setSmallIcon(Icon.createWithContentUri(Uri.parse("content://something"))) + .build(); StatusBarNotification sbn = new StatusBarNotification(PKG_P, PKG_P, id1, tag1, uid, uid, n, mUser, null, uid); NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel); @@ -833,6 +835,27 @@ public class NotificationRecordTest extends UiServiceTestCase { } @Test + public void testCalculateGrantableUris_PappProvided_invalidSound() { + IActivityManager am = mock(IActivityManager.class); + UriGrantsManagerInternal ugm = mock(UriGrantsManagerInternal.class); + when(ugm.checkGrantUriPermission(anyInt(), eq(null), any(Uri.class), + anyInt(), anyInt())).thenThrow(new SecurityException()); + + channel.setSound(Uri.parse("content://something"), mock(AudioAttributes.class)); + + Notification n = mock(Notification.class); + when(n.getChannelId()).thenReturn(channel.getId()); + StatusBarNotification sbn = + new StatusBarNotification(PKG_P, PKG_P, id1, tag1, uid, uid, n, mUser, null, uid); + NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel); + record.mAm = am; + record.mUgmInternal = ugm; + + record.calculateGrantableUris(); + assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, record.getSound()); + } + + @Test public void testCalculateGrantableUris_PuserOverridden() { IActivityManager am = mock(IActivityManager.class); UriGrantsManagerInternal ugm = mock(UriGrantsManagerInternal.class); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java index 1d25b54207c4..0bfd2020622f 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java @@ -52,6 +52,7 @@ import android.content.pm.PackageManagerInternal; import android.os.Looper; import android.os.UserHandle; import android.os.UserManager; +import android.telecom.TelecomManager; import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; @@ -167,7 +168,7 @@ public class RoleObserverTest extends UiServiceTestCase { mock(StatsManager.class), mock(TelephonyManager.class), mock(ActivityManagerInternal.class), mock(MultiRateLimiter.class), mock(PermissionHelper.class), - mock(UsageStatsManagerInternal.class)); + mock(UsageStatsManagerInternal.class), mock (TelecomManager.class)); } catch (SecurityException e) { if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) { throw e; 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 fe59185a6893..82e54110b971 100644 --- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java @@ -20,6 +20,8 @@ import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_EXT_ENABLE_ON_BACK import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.window.BackNavigationInfo.typeToString; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; + import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; @@ -29,9 +31,12 @@ 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.atLeastOnce; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.annotation.NonNull; @@ -39,6 +44,7 @@ import android.annotation.Nullable; import android.hardware.HardwareBuffer; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; +import android.view.SurfaceControl; import android.view.WindowManager; import android.window.BackEvent; import android.window.BackNavigationInfo; @@ -77,22 +83,29 @@ public class BackNavigationControllerTests extends WindowTestsBase { @Test public void backNavInfo_HomeWhenBackToLauncher() { - IOnBackInvokedCallback callback = withSystemCallback(createTopTaskWithActivity()); + IOnBackInvokedCallback callback = + withCallback(createTopTaskWithActivity(), OnBackInvokedDispatcher.PRIORITY_SYSTEM); - BackNavigationInfo backNavigationInfo = startBackNavigation(); + SurfaceControl.Transaction tx = mock(SurfaceControl.Transaction.class); + BackNavigationInfo backNavigationInfo = mBackNavigationController.startBackNavigation(mWm, + tx); assertWithMessage("BackNavigationInfo").that(backNavigationInfo).isNotNull(); assertThat(backNavigationInfo.getDepartingAnimationTarget()).isNotNull(); assertThat(backNavigationInfo.getTaskWindowConfiguration()).isNotNull(); assertThat(backNavigationInfo.getOnBackInvokedCallback()).isEqualTo(callback); assertThat(typeToString(backNavigationInfo.getType())) .isEqualTo(typeToString(BackNavigationInfo.TYPE_RETURN_TO_HOME)); + + verify(tx, atLeastOnce()).apply(); + verify(tx, times(1)).reparent(any(), + eq(backNavigationInfo.getDepartingAnimationTarget().leash)); } @Test public void backTypeCrossTaskWhenBackToPreviousTask() { Task taskA = createTask(mDefaultDisplay); createActivityRecord(taskA); - withSystemCallback(createTopTaskWithActivity()); + withCallback(createTopTaskWithActivity(), OnBackInvokedDispatcher.PRIORITY_SYSTEM); BackNavigationInfo backNavigationInfo = startBackNavigation(); assertWithMessage("BackNavigationInfo").that(backNavigationInfo).isNotNull(); assertThat(typeToString(backNavigationInfo.getType())) @@ -144,7 +157,7 @@ public class BackNavigationControllerTests extends WindowTestsBase { @Test public void preparesForBackToHome() { Task task = createTopTaskWithActivity(); - withSystemCallback(task); + withCallback(task, OnBackInvokedDispatcher.PRIORITY_SYSTEM); BackNavigationInfo backNavigationInfo = startBackNavigation(); assertThat(typeToString(backNavigationInfo.getType())) @@ -154,7 +167,8 @@ public class BackNavigationControllerTests extends WindowTestsBase { @Test public void backTypeCallback() { Task task = createTopTaskWithActivity(); - IOnBackInvokedCallback appCallback = withAppCallback(task); + IOnBackInvokedCallback appCallback = + withCallback(task, OnBackInvokedDispatcher.PRIORITY_DEFAULT); BackNavigationInfo backNavigationInfo = startBackNavigation(); assertThat(typeToString(backNavigationInfo.getType())) @@ -215,20 +229,63 @@ public class BackNavigationControllerTests extends WindowTestsBase { 1, appLatch.getCount()); } - private IOnBackInvokedCallback withSystemCallback(Task task) { - IOnBackInvokedCallback callback = createOnBackInvokedCallback(); - task.getTopMostActivity().getTopChild().setOnBackInvokedCallbackInfo( - new OnBackInvokedCallbackInfo(callback, OnBackInvokedDispatcher.PRIORITY_SYSTEM)); - return callback; + @Test + public void returnsImeCallback_imeVisible() { + // Set up a top activity with a default priority callback. + IOnBackInvokedCallback appCallback = + withCallback(createTopTaskWithActivity(), OnBackInvokedDispatcher.PRIORITY_DEFAULT); + IOnBackInvokedCallback imeCallback = createOnBackInvokedCallback(); + + // Set up an IME window with also a default priority callback. + final DisplayArea.Tokens imeContainer = mDisplayContent.getImeContainer(); + final WindowState imeWindow = createImeWindow(); + imeWindow.setOnBackInvokedCallbackInfo( + new OnBackInvokedCallbackInfo( + imeCallback, OnBackInvokedDispatcher.PRIORITY_DEFAULT)); + spyOn(imeContainer); + // Simulate IME becoming visible. + doReturn(true).when(imeContainer).isVisible(); + doReturn(imeWindow).when(imeContainer).getWindow(any()); + BackNavigationInfo backNavigationInfo = startBackNavigation(); + + // Expect the IME callback to be selected. + assertThat(backNavigationInfo.getOnBackInvokedCallback()).isEqualTo(imeCallback); } - private IOnBackInvokedCallback withAppCallback(Task task) { + @Test + public void returnsAppOverlayCallback_imeVisible() { + // Set up a top activity with an overlay priority callback. + IOnBackInvokedCallback appCallback = + withCallback(createTopTaskWithActivity(), OnBackInvokedDispatcher.PRIORITY_OVERLAY); + IOnBackInvokedCallback imeCallback = createOnBackInvokedCallback(); + + // Set up an IME window with a default priority callback. + final DisplayArea.Tokens imeContainer = mDisplayContent.getImeContainer(); + final WindowState imeWindow = createImeWindow(); + imeWindow.setOnBackInvokedCallbackInfo( + new OnBackInvokedCallbackInfo( + imeCallback, OnBackInvokedDispatcher.PRIORITY_DEFAULT)); + spyOn(imeContainer); + // Simulate IME becoming visible. + doReturn(true).when(imeContainer).isVisible(); + doReturn(imeWindow).when(imeContainer).getWindow(any()); + BackNavigationInfo backNavigationInfo = startBackNavigation(); + + // Expect the app callback to be selected. + assertThat(backNavigationInfo.getOnBackInvokedCallback()).isEqualTo(appCallback); + } + + private IOnBackInvokedCallback withCallback(Task task, int priority) { IOnBackInvokedCallback callback = createOnBackInvokedCallback(); task.getTopMostActivity().getTopChild().setOnBackInvokedCallbackInfo( - new OnBackInvokedCallbackInfo(callback, OnBackInvokedDispatcher.PRIORITY_DEFAULT)); + new OnBackInvokedCallbackInfo(callback, priority)); return callback; } + private WindowState createImeWindow() { + return createWindow(null, W_INPUT_METHOD, "mImeWindow", 12345 /* fake ime uide */); + } + @Nullable private BackNavigationInfo startBackNavigation() { return mBackNavigationController.startBackNavigation(mWm, new StubTransaction()); diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java index 762c08f99d94..8ef9ada8995f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java @@ -300,6 +300,81 @@ public class RootWindowContainerTests extends WindowTestsBase { assertTrue(firstActivity.mRequestForceTransition); } + /** + * When there is only one activity in the Task, and the activity is requesting to enter PIP, the + * whole Task should enter PIP. + */ + @Test + public void testSingleActivityTaskEnterPip() { + final Task fullscreenTask = mRootWindowContainer.getDefaultTaskDisplayArea().createRootTask( + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); + final ActivityRecord activity = new ActivityBuilder(mAtm) + .setTask(fullscreenTask) + .build(); + final Task task = activity.getTask(); + + // Move activity to pinned root task. + mRootWindowContainer.moveActivityToPinnedRootTask(activity, + null /* launchIntoPipHostActivity */, "test"); + + // Ensure a task has moved over. + ensureTaskPlacement(task, activity); + assertTrue(task.inPinnedWindowingMode()); + } + + /** + * When there is only one activity in the Task, and the activity is requesting to enter PIP, the + * whole Task should enter PIP even if the activity is in a TaskFragment. + */ + @Test + public void testSingleActivityInTaskFragmentEnterPip() { + final Task fullscreenTask = mRootWindowContainer.getDefaultTaskDisplayArea().createRootTask( + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); + final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm) + .setParentTask(fullscreenTask) + .createActivityCount(1) + .build(); + final ActivityRecord activity = taskFragment.getTopMostActivity(); + final Task task = activity.getTask(); + + // Move activity to pinned root task. + mRootWindowContainer.moveActivityToPinnedRootTask(activity, + null /* launchIntoPipHostActivity */, "test"); + + // Ensure a task has moved over. + ensureTaskPlacement(task, activity); + assertTrue(task.inPinnedWindowingMode()); + } + + /** + * When there is one TaskFragment with two activities in the Task, the activity requests to + * enter PIP, that activity will be move to PIP root task. + */ + @Test + public void testMultipleActivitiesInTaskFragmentEnterPip() { + final Task fullscreenTask = mRootWindowContainer.getDefaultTaskDisplayArea().createRootTask( + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); + final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm) + .setParentTask(fullscreenTask) + .createActivityCount(2) + .build(); + final ActivityRecord firstActivity = taskFragment.getTopMostActivity(); + final ActivityRecord secondActivity = taskFragment.getBottomMostActivity(); + + // Move first activity to pinned root task. + mRootWindowContainer.moveActivityToPinnedRootTask(firstActivity, + null /* launchIntoPipHostActivity */, "test"); + + final TaskDisplayArea taskDisplayArea = fullscreenTask.getDisplayArea(); + final Task pinnedRootTask = taskDisplayArea.getRootPinnedTask(); + + // Ensure a task has moved over. + ensureTaskPlacement(pinnedRootTask, firstActivity); + ensureTaskPlacement(fullscreenTask, secondActivity); + assertTrue(pinnedRootTask.inPinnedWindowingMode()); + assertEquals(WINDOWING_MODE_FULLSCREEN, fullscreenTask.getWindowingMode()); + } + private static void ensureTaskPlacement(Task task, ActivityRecord... activities) { final ArrayList<ActivityRecord> taskActivities = new ArrayList<>(); diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java index 37719fecd7e4..a297608af480 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java @@ -16,6 +16,9 @@ package com.android.server.wm; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; + import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.WindowContainer.POSITION_TOP; @@ -28,6 +31,8 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; 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.clearInvocations; import static org.mockito.Mockito.mock; @@ -435,6 +440,115 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { } @Test + public void testTaskFragmentInPip_startActivityInTaskFragment() { + setupTaskFragmentInPip(); + final ActivityRecord activity = mTaskFragment.getTopMostActivity(); + final IBinder errorToken = new Binder(); + spyOn(mAtm.getActivityStartController()); + spyOn(mAtm.mWindowOrganizerController); + + // Not allow to start activity in a TaskFragment that is in a PIP Task. + mTransaction.startActivityInTaskFragment( + mFragmentToken, activity.token, new Intent(), null /* activityOptions */) + .setErrorCallbackToken(errorToken); + mAtm.mWindowOrganizerController.applyTransaction(mTransaction); + + verify(mAtm.getActivityStartController(), never()).startActivityInTaskFragment(any(), any(), + any(), any(), anyInt(), anyInt()); + verify(mAtm.mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer), + eq(errorToken), any(IllegalArgumentException.class)); + } + + @Test + public void testTaskFragmentInPip_reparentActivityToTaskFragment() { + setupTaskFragmentInPip(); + final ActivityRecord activity = createActivityRecord(mDisplayContent); + final IBinder errorToken = new Binder(); + spyOn(mAtm.mWindowOrganizerController); + + // Not allow to reparent activity to a TaskFragment that is in a PIP Task. + mTransaction.reparentActivityToTaskFragment(mFragmentToken, activity.token) + .setErrorCallbackToken(errorToken); + mAtm.mWindowOrganizerController.applyTransaction(mTransaction); + + verify(mAtm.mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer), + eq(errorToken), any(IllegalArgumentException.class)); + assertNull(activity.getOrganizedTaskFragment()); + } + + @Test + public void testTaskFragmentInPip_setAdjacentTaskFragment() { + setupTaskFragmentInPip(); + final IBinder errorToken = new Binder(); + spyOn(mAtm.mWindowOrganizerController); + + // Not allow to set adjacent on a TaskFragment that is in a PIP Task. + mTransaction.setAdjacentTaskFragments(mFragmentToken, null /* fragmentToken2 */, + null /* options */) + .setErrorCallbackToken(errorToken); + mAtm.mWindowOrganizerController.applyTransaction(mTransaction); + + verify(mAtm.mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer), + eq(errorToken), any(IllegalArgumentException.class)); + verify(mTaskFragment, never()).setAdjacentTaskFragment(any(), anyBoolean()); + } + + @Test + public void testTaskFragmentInPip_createTaskFragment() { + mController.registerOrganizer(mIOrganizer); + final Task pipTask = createTask(mDisplayContent, WINDOWING_MODE_PINNED, + ACTIVITY_TYPE_STANDARD); + final ActivityRecord activity = createActivityRecord(pipTask); + final IBinder fragmentToken = new Binder(); + final IBinder errorToken = new Binder(); + spyOn(mAtm.mWindowOrganizerController); + + // Not allow to create TaskFragment in a PIP Task. + createTaskFragmentFromOrganizer(mTransaction, activity, fragmentToken); + mTransaction.setErrorCallbackToken(errorToken); + mAtm.mWindowOrganizerController.applyTransaction(mTransaction); + + verify(mAtm.mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer), + eq(errorToken), any(IllegalArgumentException.class)); + assertNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken)); + } + + @Test + public void testTaskFragmentInPip_deleteTaskFragment() { + setupTaskFragmentInPip(); + final IBinder errorToken = new Binder(); + spyOn(mAtm.mWindowOrganizerController); + + // Not allow to delete a TaskFragment that is in a PIP Task. + mTransaction.deleteTaskFragment(mFragmentWindowToken) + .setErrorCallbackToken(errorToken); + mAtm.mWindowOrganizerController.applyTransaction(mTransaction); + + verify(mAtm.mWindowOrganizerController).sendTaskFragmentOperationFailure(eq(mIOrganizer), + eq(errorToken), any(IllegalArgumentException.class)); + assertNotNull(mAtm.mWindowOrganizerController.getTaskFragment(mFragmentToken)); + + // Allow organizer to delete empty TaskFragment for cleanup. + final Task task = mTaskFragment.getTask(); + mTaskFragment.removeChild(mTaskFragment.getTopMostActivity()); + mAtm.mWindowOrganizerController.applyTransaction(mTransaction); + + assertNull(mAtm.mWindowOrganizerController.getTaskFragment(mFragmentToken)); + assertNull(task.getTopChild()); + } + + @Test + public void testTaskFragmentInPip_setConfig() { + setupTaskFragmentInPip(); + spyOn(mAtm.mWindowOrganizerController); + + // Set bounds is ignored on a TaskFragment that is in a PIP Task. + mTransaction.setBounds(mFragmentWindowToken, new Rect(0, 0, 100, 100)); + + verify(mTaskFragment, never()).setBounds(any()); + } + + @Test public void testDeferPendingTaskFragmentEventsOfInvisibleTask() { // Task - TaskFragment - Activity. final Task task = createTask(mDisplayContent); @@ -643,4 +757,20 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { fail(); } } + + /** Setups an embedded TaskFragment in a PIP Task. */ + private void setupTaskFragmentInPip() { + mOrganizer.applyTransaction(mTransaction); + mController.registerOrganizer(mIOrganizer); + mTaskFragment = new TaskFragmentBuilder(mAtm) + .setCreateParentTask() + .setFragmentToken(mFragmentToken) + .setOrganizer(mOrganizer) + .createActivityCount(1) + .build(); + mFragmentWindowToken = mTaskFragment.mRemoteToken.toWindowContainerToken(); + mAtm.mWindowOrganizerController.mLaunchTaskFragments + .put(mFragmentToken, mTaskFragment); + mTaskFragment.getTask().setWindowingMode(WINDOWING_MODE_PINNED); + } } 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 971826dd09b6..54fa4e4bf7ec 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java @@ -16,6 +16,10 @@ package com.android.server.wm; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; + import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.never; @@ -28,6 +32,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.clearInvocations; +import android.content.res.Configuration; import android.graphics.Rect; import android.os.Binder; import android.platform.test.annotations.Presubmit; @@ -202,4 +207,121 @@ public class TaskFragmentTest extends WindowTestsBase { assertTrue(primaryActivity.supportsEnterPipOnTaskSwitch); assertFalse(secondaryActivity.supportsEnterPipOnTaskSwitch); } + + @Test + public void testEmbeddedTaskFragmentEnterPip_singleActivity_resetOrganizerOverrideConfig() { + final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm) + .setOrganizer(mOrganizer) + .setFragmentToken(new Binder()) + .setCreateParentTask() + .createActivityCount(1) + .build(); + final Task task = taskFragment.getTask(); + final ActivityRecord activity = taskFragment.getTopMostActivity(); + final Rect taskFragmentBounds = new Rect(0, 0, 300, 1000); + task.setWindowingMode(WINDOWING_MODE_FULLSCREEN); + taskFragment.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); + taskFragment.setBounds(taskFragmentBounds); + + assertEquals(taskFragmentBounds, activity.getBounds()); + assertEquals(WINDOWING_MODE_MULTI_WINDOW, activity.getWindowingMode()); + + // Move activity to pinned root task. + mRootWindowContainer.moveActivityToPinnedRootTask(activity, + null /* launchIntoPipHostActivity */, "test"); + + // Ensure taskFragment requested config is reset. + assertEquals(taskFragment, activity.getOrganizedTaskFragment()); + assertEquals(task, activity.getTask()); + assertTrue(task.inPinnedWindowingMode()); + assertTrue(taskFragment.inPinnedWindowingMode()); + final Rect taskBounds = task.getBounds(); + assertEquals(taskBounds, taskFragment.getBounds()); + assertEquals(taskBounds, activity.getBounds()); + assertEquals(Configuration.EMPTY, taskFragment.getRequestedOverrideConfiguration()); + } + + @Test + public void testEmbeddedTaskFragmentEnterPip_multiActivities_notifyOrganizer() { + final Task task = createTask(mDisplayContent); + final TaskFragment taskFragment0 = new TaskFragmentBuilder(mAtm) + .setParentTask(task) + .setOrganizer(mOrganizer) + .setFragmentToken(new Binder()) + .createActivityCount(1) + .build(); + final TaskFragment taskFragment1 = new TaskFragmentBuilder(mAtm) + .setParentTask(task) + .setOrganizer(mOrganizer) + .setFragmentToken(new Binder()) + .createActivityCount(1) + .build(); + final ActivityRecord activity0 = taskFragment0.getTopMostActivity(); + spyOn(mAtm.mTaskFragmentOrganizerController); + + // Move activity to pinned. + mRootWindowContainer.moveActivityToPinnedRootTask(activity0, + null /* launchIntoPipHostActivity */, "test"); + + // Ensure taskFragment requested config is reset. + assertTrue(taskFragment0.mClearedTaskFragmentForPip); + assertFalse(taskFragment1.mClearedTaskFragmentForPip); + final TaskFragmentInfo info = taskFragment0.getTaskFragmentInfo(); + assertTrue(info.isTaskFragmentClearedForPip()); + assertTrue(info.isEmpty()); + verify(mAtm.mTaskFragmentOrganizerController) + .dispatchPendingInfoChangedEvent(taskFragment0); + } + + @Test + public void testActivityHasOverlayOverUntrustedModeEmbedded() { + final Task rootTask = createTask(mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, + ACTIVITY_TYPE_STANDARD); + final Task leafTask0 = new TaskBuilder(mSupervisor) + .setParentTaskFragment(rootTask) + .build(); + final TaskFragment organizedTf = new TaskFragmentBuilder(mAtm) + .createActivityCount(2) + .setParentTask(leafTask0) + .setFragmentToken(new Binder()) + .setOrganizer(mOrganizer) + .build(); + final ActivityRecord activity0 = organizedTf.getBottomMostActivity(); + final ActivityRecord activity1 = organizedTf.getTopMostActivity(); + // Bottom activity is untrusted embedding. Top activity is trusted embedded. + // Activity0 has overlay over untrusted mode embedded. + activity0.info.applicationInfo.uid = DEFAULT_TASK_FRAGMENT_ORGANIZER_UID + 1; + activity1.info.applicationInfo.uid = DEFAULT_TASK_FRAGMENT_ORGANIZER_UID; + doReturn(true).when(organizedTf).isAllowedToEmbedActivityInUntrustedMode(activity0); + + assertTrue(activity0.hasOverlayOverUntrustedModeEmbedded()); + assertFalse(activity1.hasOverlayOverUntrustedModeEmbedded()); + + // Both activities are trusted embedded. + // None of the two has overlay over untrusted mode embedded. + activity0.info.applicationInfo.uid = DEFAULT_TASK_FRAGMENT_ORGANIZER_UID; + + assertFalse(activity0.hasOverlayOverUntrustedModeEmbedded()); + assertFalse(activity1.hasOverlayOverUntrustedModeEmbedded()); + + // Bottom activity is trusted embedding. Top activity is untrusted embedded. + // None of the two has overlay over untrusted mode embedded. + activity1.info.applicationInfo.uid = DEFAULT_TASK_FRAGMENT_ORGANIZER_UID + 1; + + assertFalse(activity0.hasOverlayOverUntrustedModeEmbedded()); + assertFalse(activity1.hasOverlayOverUntrustedModeEmbedded()); + + // There is an activity in a different leaf task on top of activity0 and activity1. + // None of the two has overlay over untrusted mode embedded because it is not the same Task. + final Task leafTask1 = new TaskBuilder(mSupervisor) + .setParentTaskFragment(rootTask) + .setOnTop(true) + .setCreateActivity(true) + .build(); + final ActivityRecord activity2 = leafTask1.getTopMostActivity(); + activity2.info.applicationInfo.uid = DEFAULT_TASK_FRAGMENT_ORGANIZER_UID + 2; + + assertFalse(activity0.hasOverlayOverUntrustedModeEmbedded()); + assertFalse(activity1.hasOverlayOverUntrustedModeEmbedded()); + } } diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index b2cc104834e6..1b07e9a69446 100644 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -237,7 +237,12 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser @Override public void onUEvent(UEventObserver.UEvent event) { if (DEBUG) Slog.v(TAG, "USB UEVENT: " + event.toString()); - sEventLogger.log(new UsbDeviceLogger.StringEvent("USB UEVENT: " + event.toString())); + if (sEventLogger != null) { + sEventLogger.log(new UsbDeviceLogger.StringEvent("USB UEVENT: " + + event.toString())); + } else { + if (DEBUG) Slog.d(TAG, "sEventLogger == null"); + } String state = event.get("USB_STATE"); String accessory = event.get("ACCESSORY"); diff --git a/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java b/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java index 600fc27f5103..94273a37abcd 100644 --- a/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java +++ b/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java @@ -725,5 +725,15 @@ public final class UsbPortAidl implements UsbPortHal { e); } } + + @Override + public String getInterfaceHash() { + return IUsbCallback.HASH; + } + + @Override + public int getInterfaceVersion() { + return IUsbCallback.VERSION; + } } } diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java index ee2d23558010..b71669046ee9 100644 --- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java +++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java @@ -84,9 +84,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { private static final int INVALID_VALUE = Integer.MIN_VALUE; - /** Maximum time to wait for a model stop confirmation before giving up. */ - private static final long STOP_TIMEOUT_MS = 5000; - /** The {@link ModuleProperties} for the system, or null if none exists. */ final ModuleProperties mModuleProperties; @@ -398,20 +395,8 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { return STATUS_OK; } - int status = prepareForRecognition(modelData); - if (status != STATUS_OK) { - Slog.w(TAG, "startRecognition failed to prepare model for recognition"); - return status; - } - status = startRecognitionLocked(modelData, + return updateRecognitionLocked(modelData, false /* Don't notify for synchronous calls */); - - // Initialize power save, call active state monitoring logic. - if (status == STATUS_OK) { - initializeDeviceStateListeners(); - } - - return status; } } @@ -560,7 +545,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { } } - if (unloadModel && modelData.isModelLoaded()) { + if (unloadModel && (modelData.isModelLoaded() || modelData.isStopPending())) { Slog.d(TAG, "Unloading previously loaded stale model."); if (mModule == null) { return STATUS_ERROR; @@ -834,7 +819,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { } if (!event.recognitionStillActive) { - model.setStoppedLocked(); + model.setStopped(); } try { @@ -920,8 +905,8 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { Slog.w(TAG, "Recognition aborted"); MetricsLogger.count(mContext, "sth_recognition_aborted", 1); ModelData modelData = getModelDataForLocked(event.soundModelHandle); - if (modelData != null && modelData.isModelStarted()) { - modelData.setStoppedLocked(); + if (modelData != null && (modelData.isModelStarted() || modelData.isStopPending())) { + modelData.setStopped(); try { IRecognitionStatusCallback callback = modelData.getCallback(); if (callback != null) { @@ -932,6 +917,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { } catch (RemoteException e) { Slog.w(TAG, "RemoteException in onRecognitionPaused", e); } + updateRecognitionLocked(modelData, true); } } @@ -978,7 +964,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { } if (!event.recognitionStillActive) { - modelData.setStoppedLocked(); + modelData.setStopped(); } try { @@ -1011,16 +997,22 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { private int updateRecognitionLocked(ModelData model, boolean notifyClientOnError) { boolean shouldStartModel = model.isRequested() && isRecognitionAllowedByDeviceState(model); - if (shouldStartModel == model.isModelStarted()) { + if (shouldStartModel == model.isModelStarted() || model.isStopPending()) { // No-op. return STATUS_OK; } if (shouldStartModel) { int status = prepareForRecognition(model); if (status != STATUS_OK) { + Slog.w(TAG, "startRecognition failed to prepare model for recognition"); return status; } - return startRecognitionLocked(model, notifyClientOnError); + status = startRecognitionLocked(model, notifyClientOnError); + // Initialize power save, call active state monitoring logic. + if (status == STATUS_OK) { + initializeDeviceStateListeners(); + } + return status; } else { return stopRecognitionLocked(model, notifyClientOnError); } @@ -1203,10 +1195,13 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { if (mModule == null) { return; } - if (modelData.isModelStarted()) { + if (modelData.isStopPending()) { + // No need to wait for the stop to be confirmed. + modelData.setStopped(); + } else if (modelData.isModelStarted()) { Slog.d(TAG, "Stopping previously started dangling model " + modelData.getHandle()); if (mModule.stopRecognition(modelData.getHandle()) == STATUS_OK) { - modelData.setStoppedLocked(); + modelData.setStopped(); modelData.setRequested(false); } else { Slog.e(TAG, "Failed to stop model " + modelData.getHandle()); @@ -1255,7 +1250,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { private ModelData getOrCreateGenericModelDataLocked(UUID modelId) { ModelData modelData = mModelDataMap.get(modelId); if (modelData == null) { - modelData = createGenericModelData(modelId); + modelData = ModelData.createGenericModelData(modelId); mModelDataMap.put(modelId, modelData); } else if (!modelData.isGenericModel()) { Slog.e(TAG, "UUID already used for non-generic model."); @@ -1287,7 +1282,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { mKeyphraseUuidMap.remove(keyphraseId); mModelDataMap.remove(modelId); mKeyphraseUuidMap.put(keyphraseId, modelId); - ModelData modelData = createKeyphraseModelData(modelId); + ModelData modelData = ModelData.createKeyphraseModelData(modelId); mModelDataMap.put(modelId, modelData); return modelData; } @@ -1419,26 +1414,18 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { Slog.w(TAG, "RemoteException in onError", e); } } - return status; - } - - // Wait for model to be stopped. - try { - modelData.waitStoppedLocked(STOP_TIMEOUT_MS); - } catch (InterruptedException e) { - Slog.e(TAG, "Didn't receive model stop callback"); - return SoundTrigger.STATUS_ERROR; - } - - MetricsLogger.count(mContext, "sth_stop_recognition_success", 1); - // Notify of pause if needed. - if (notify) { - try { - callback.onRecognitionPaused(); - } catch (DeadObjectException e) { - forceStopAndUnloadModelLocked(modelData, e); - } catch (RemoteException e) { - Slog.w(TAG, "RemoteException in onRecognitionPaused", e); + } else { + modelData.setStopPending(); + MetricsLogger.count(mContext, "sth_stop_recognition_success", 1); + // Notify of pause if needed. + if (notify) { + try { + callback.onRecognitionPaused(); + } catch (DeadObjectException e) { + forceStopAndUnloadModelLocked(modelData, e); + } catch (RemoteException e) { + Slog.w(TAG, "RemoteException in onRecognitionPaused", e); + } } } if (DBG) { @@ -1473,7 +1460,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { // This class encapsulates the callbacks, state, handles and any other information that // represents a model. - private class ModelData { + private static class ModelData { // Model not loaded (and hence not started). static final int MODEL_NOTLOADED = 0; @@ -1483,6 +1470,9 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { // Started implies model was successfully loaded and start was called. static final int MODEL_STARTED = 2; + // Model stop request has been sent. Waiting for an event to signal model being stopped. + static final int MODEL_STOP_PENDING = 3; + // One of MODEL_NOTLOADED, MODEL_LOADED, MODEL_STARTED (which implies loaded). private int mModelState; private UUID mModelId; @@ -1530,9 +1520,17 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { mModelType = modelType; } + static ModelData createKeyphraseModelData(UUID modelId) { + return new ModelData(modelId, SoundModel.TYPE_KEYPHRASE); + } + + static ModelData createGenericModelData(UUID modelId) { + return new ModelData(modelId, SoundModel.TYPE_GENERIC_SOUND); + } + // Note that most of the functionality in this Java class will not work for // SoundModel.TYPE_UNKNOWN nevertheless we have it since lower layers support it. - ModelData createModelDataOfUnknownType(UUID modelId) { + static ModelData createModelDataOfUnknownType(UUID modelId) { return new ModelData(modelId, SoundModel.TYPE_UNKNOWN); } @@ -1552,24 +1550,20 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { return mModelState == MODEL_NOTLOADED; } + synchronized boolean isStopPending() { + return mModelState == MODEL_STOP_PENDING; + } + synchronized void setStarted() { mModelState = MODEL_STARTED; } - synchronized void setStoppedLocked() { + synchronized void setStopped() { mModelState = MODEL_LOADED; - mLock.notifyAll(); } - void waitStoppedLocked(long timeoutMs) throws InterruptedException { - long deadline = System.currentTimeMillis() + timeoutMs; - while (mModelState == MODEL_STARTED) { - long waitTime = deadline - System.currentTimeMillis(); - if (waitTime <= 0) { - throw new InterruptedException(); - } - mLock.wait(waitTime); - } + synchronized void setStopPending() { + mModelState = MODEL_STOP_PENDING; } synchronized void setLoaded() { @@ -1589,7 +1583,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { mRecognitionConfig = null; mRequested = false; mCallback = null; - notifyAll(); } synchronized void clearCallback() { @@ -1694,12 +1687,4 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { return "Model type: " + type + "\n"; } } - - ModelData createKeyphraseModelData(UUID modelId) { - return new ModelData(modelId, SoundModel.TYPE_KEYPHRASE); - } - - ModelData createGenericModelData(UUID modelId) { - return new ModelData(modelId, SoundModel.TYPE_GENERIC_SOUND); - } } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java index 8d4a0176e3be..5b6e6863c0df 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java @@ -39,10 +39,13 @@ import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENT import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__NORMAL_DETECTOR; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECTED; -import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_EXCEPTION; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_SECURITY_EXCEPTION; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_TIMEOUT; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_UNEXPECTED_CALLBACK; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__KEYPHRASE_TRIGGER; import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__REJECTED; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__REJECTED_FROM_RESTART; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__REJECT_UNEXPECTED_CALLBACK; import static com.android.server.voiceinteraction.SoundTriggerSessionPermissionsDecorator.enforcePermissionForPreflight; import android.annotation.NonNull; @@ -133,6 +136,13 @@ final class HotwordDetectionConnection { private static final int METRICS_INIT_CALLBACK_STATE_SUCCESS = HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_SUCCESS; + private static final int METRICS_KEYPHRASE_TRIGGERED_DETECT_SECURITY_EXCEPTION = + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_SECURITY_EXCEPTION; + private static final int METRICS_KEYPHRASE_TRIGGERED_DETECT_UNEXPECTED_CALLBACK = + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_UNEXPECTED_CALLBACK; + private static final int METRICS_KEYPHRASE_TRIGGERED_REJECT_UNEXPECTED_CALLBACK = + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__REJECT_UNEXPECTED_CALLBACK; + private final Executor mAudioCopyExecutor = Executors.newCachedThreadPool(); // TODO: This may need to be a Handler(looper) private final ScheduledExecutorService mScheduledExecutorService = @@ -575,7 +585,7 @@ final class HotwordDetectionConnection { Slog.i(TAG, "Ignoring #onDetected due to a process restart"); HotwordMetricsLogger.writeKeyphraseTriggerEvent( mDetectorType, - HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_EXCEPTION); + METRICS_KEYPHRASE_TRIGGERED_DETECT_UNEXPECTED_CALLBACK); return; } mValidatingDspTrigger = false; @@ -584,7 +594,7 @@ final class HotwordDetectionConnection { } catch (SecurityException e) { HotwordMetricsLogger.writeKeyphraseTriggerEvent( mDetectorType, - HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_EXCEPTION); + METRICS_KEYPHRASE_TRIGGERED_DETECT_SECURITY_EXCEPTION); throw e; } externalCallback.onKeyphraseDetected(recognitionEvent, result); @@ -614,7 +624,7 @@ final class HotwordDetectionConnection { Slog.i(TAG, "Ignoring #onRejected due to a process restart"); HotwordMetricsLogger.writeKeyphraseTriggerEvent( mDetectorType, - HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_EXCEPTION); + METRICS_KEYPHRASE_TRIGGERED_REJECT_UNEXPECTED_CALLBACK); return; } mValidatingDspTrigger = false; @@ -687,6 +697,9 @@ final class HotwordDetectionConnection { // rejection. This also allows the Interactor to startReco again try { mCallback.onRejected(new HotwordRejectedResult.Builder().build()); + HotwordMetricsLogger.writeKeyphraseTriggerEvent( + mDetectorType, + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__REJECTED_FROM_RESTART); } catch (RemoteException e) { Slog.w(TAG, "Failed to call #rejected"); } diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl index 07e18d524701..37403a806daf 100644 --- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl +++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl @@ -355,6 +355,11 @@ interface ITelecomService { void setTestDefaultCallRedirectionApp(String packageName); + /** + * @see TelecomServiceImpl#requestLogMark + */ + void requestLogMark(in String message); + void setTestPhoneAcctSuggestionComponent(String flattenedComponentName); void setTestDefaultCallScreeningApp(String packageName); diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index a6a7c841c5ec..9c886aada728 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -832,6 +832,17 @@ public class CarrierConfigManager { "dial_string_replace_string_array"; /** + * Specifies a map from dialstrings to replacements for international roaming network service + * numbers which cannot be replaced on the carrier side. + * <p> + * Individual entries have the format: + * [dialstring to replace]:[replacement] + * @hide + */ + public static final String KEY_INTERNATIONAL_ROAMING_DIAL_STRING_REPLACE_STRING_ARRAY = + "international_roaming_dial_string_replace_string_array"; + + /** * Flag specifying whether WFC over IMS supports the "wifi only" option. If false, the wifi * calling settings will not include an option for "wifi only". If true, the wifi calling * settings will include an option for "wifi only" @@ -8713,6 +8724,7 @@ public class CarrierConfigManager { sDefaults.putStringArray(KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY, null); sDefaults.putStringArray(KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY, null); sDefaults.putStringArray(KEY_DIAL_STRING_REPLACE_STRING_ARRAY, null); + sDefaults.putStringArray(KEY_INTERNATIONAL_ROAMING_DIAL_STRING_REPLACE_STRING_ARRAY, null); sDefaults.putBoolean(KEY_FORCE_HOME_NETWORK_BOOL, false); sDefaults.putInt(KEY_GSM_DTMF_TONE_DELAY_INT, 0); sDefaults.putInt(KEY_IMS_DTMF_TONE_DELAY_INT, 0); diff --git a/telephony/java/android/telephony/PhysicalChannelConfig.java b/telephony/java/android/telephony/PhysicalChannelConfig.java index d91134e33ef3..d978f5701eca 100644 --- a/telephony/java/android/telephony/PhysicalChannelConfig.java +++ b/telephony/java/android/telephony/PhysicalChannelConfig.java @@ -23,16 +23,12 @@ import android.os.Parcel; import android.os.Parcelable; import android.telephony.Annotation.NetworkType; -import com.android.telephony.Rlog; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.Objects; public final class PhysicalChannelConfig implements Parcelable { - static final String TAG = "PhysicalChannelConfig"; - // TODO(b/72993578) consolidate these enums in a central location. /** @hide */ @Retention(RetentionPolicy.SOURCE) @@ -571,21 +567,19 @@ public final class PhysicalChannelConfig implements Parcelable { public @NonNull Builder setNetworkType(@NetworkType int networkType) { if (!TelephonyManager.isNetworkTypeValid(networkType)) { - Rlog.e(TAG, "Builder.setNetworkType: Network type " + networkType + " is invalid."); - } else { - mNetworkType = networkType; + throw new IllegalArgumentException("Network type " + networkType + " is invalid."); } + mNetworkType = networkType; return this; } public @NonNull Builder setFrequencyRange(int frequencyRange) { if (!ServiceState.isFrequencyRangeValid(frequencyRange) && frequencyRange != ServiceState.FREQUENCY_RANGE_UNKNOWN) { - Rlog.e(TAG, "Builder.setFrequencyRange: Frequency range " + frequencyRange + throw new IllegalArgumentException("Frequency range " + frequencyRange + " is invalid."); - } else { - mFrequencyRange = frequencyRange; } + mFrequencyRange = frequencyRange; return this; } @@ -601,21 +595,19 @@ public final class PhysicalChannelConfig implements Parcelable { public @NonNull Builder setCellBandwidthDownlinkKhz(int cellBandwidthDownlinkKhz) { if (cellBandwidthDownlinkKhz < CELL_BANDWIDTH_UNKNOWN) { - Rlog.e(TAG, "Builder.setCellBandwidthDownlinkKhz: Cell downlink bandwidth(kHz) " + throw new IllegalArgumentException("Cell downlink bandwidth(kHz) " + cellBandwidthDownlinkKhz + " is invalid."); - } else { - mCellBandwidthDownlinkKhz = cellBandwidthDownlinkKhz; } + mCellBandwidthDownlinkKhz = cellBandwidthDownlinkKhz; return this; } public @NonNull Builder setCellBandwidthUplinkKhz(int cellBandwidthUplinkKhz) { if (cellBandwidthUplinkKhz < CELL_BANDWIDTH_UNKNOWN) { - Rlog.e(TAG, "Builder.setCellBandwidthUplinkKhz: Cell uplink bandwidth(kHz) " + throw new IllegalArgumentException("Cell uplink bandwidth(kHz) " + cellBandwidthUplinkKhz + " is invalid."); - } else { - mCellBandwidthUplinkKhz = cellBandwidthUplinkKhz; } + mCellBandwidthUplinkKhz = cellBandwidthUplinkKhz; return this; } @@ -632,20 +624,18 @@ public final class PhysicalChannelConfig implements Parcelable { public @NonNull Builder setPhysicalCellId(int physicalCellId) { if (physicalCellId > PHYSICAL_CELL_ID_MAXIMUM_VALUE) { - Rlog.e(TAG, "Builder.setPhysicalCellId: Physical cell ID " + physicalCellId + throw new IllegalArgumentException("Physical cell ID " + physicalCellId + " is over limit."); - } else { - mPhysicalCellId = physicalCellId; } + mPhysicalCellId = physicalCellId; return this; } public @NonNull Builder setBand(int band) { if (band <= BAND_UNKNOWN) { - Rlog.e(TAG, "Builder.setBand: Band " + band + " is invalid."); - } else { - mBand = band; + throw new IllegalArgumentException("Band " + band + " is invalid."); } + mBand = band; return this; } } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index efc2dec69a5d..71ffd6e2ec9f 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -14199,7 +14199,8 @@ public class TelephonyManager { UPDATE_AVAILABLE_NETWORKS_MULTIPLE_NETWORKS_NOT_SUPPORTED, UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE, UPDATE_AVAILABLE_NETWORKS_REMOTE_SERVICE_EXCEPTION, - UPDATE_AVAILABLE_NETWORKS_SERVICE_IS_DISABLED}) + UPDATE_AVAILABLE_NETWORKS_SERVICE_IS_DISABLED, + UPDATE_AVAILABLE_NETWORKS_SIM_PORT_NOT_AVAILABLE}) public @interface UpdateAvailableNetworksResult {} /** @@ -14258,6 +14259,12 @@ public class TelephonyManager { public static final int UPDATE_AVAILABLE_NETWORKS_SERVICE_IS_DISABLED = 10; /** + * SIM port is not available to switch to opportunistic subscription. + * @hide + */ + public static final int UPDATE_AVAILABLE_NETWORKS_SIM_PORT_NOT_AVAILABLE = 11; + + /** * Set preferred opportunistic data subscription id. * * Switch internet data to preferred opportunistic data subscription id. This api diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt index 4cddd8506df7..aaa2db768792 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt @@ -34,8 +34,6 @@ import com.android.server.wm.flicker.statusBarLayerIsVisible import com.android.server.wm.flicker.statusBarLayerRotatesScales import com.android.server.wm.flicker.statusBarWindowIsVisible import com.android.server.wm.flicker.replacesLayer -import com.android.server.wm.flicker.rules.WMFlickerServiceRuleForTestSpec -import org.junit.Rule import org.junit.Test /** @@ -45,9 +43,6 @@ abstract class CloseAppTransition(protected val testSpec: FlickerTestParameter) protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation() protected open val testApp: StandardAppHelper = SimpleAppHelper(instrumentation) - @get:Rule - val flickerRule = WMFlickerServiceRuleForTestSpec(testSpec) - /** * Specification of the test transition to execute */ diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeEditorPopupDialogTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeEditorPopupDialogTest.kt index bff099e2e7a1..6257484be9bd 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeEditorPopupDialogTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeEditorPopupDialogTest.kt @@ -91,6 +91,7 @@ class CloseImeEditorPopupDialogTest(private val testSpec: FlickerTestParameter) .then() .isVisible(FlickerComponentName.IME_SNAPSHOT) .then() + .isInvisible(FlickerComponentName.IME_SNAPSHOT) .isInvisible(FlickerComponentName.IME) } } diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt index 04fdda425edf..2f546b56f145 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt @@ -63,8 +63,12 @@ import org.junit.runners.Parameterized @FixMethodOrder(MethodSorters.NAME_ASCENDING) @Group4 class TaskTransitionTest(val testSpec: FlickerTestParameter) { - val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation() + private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation() private val mTestApp: NewTasksAppHelper = NewTasksAppHelper(instrumentation) + private val mWallpaper by lazy { + getWallpaperPackage(InstrumentationRegistry.getInstrumentation()) + ?: error("Unable to obtain wallpaper") + } @FlickerBuilderProvider fun buildFlicker(): FlickerBuilder { @@ -97,7 +101,7 @@ class TaskTransitionTest(val testSpec: FlickerTestParameter) { @Test fun wallpaperWindowIsNeverVisible() { testSpec.assertWm { - this.isNonAppWindowInvisible(WALLPAPER) + this.isNonAppWindowInvisible(mWallpaper) } } @@ -109,7 +113,7 @@ class TaskTransitionTest(val testSpec: FlickerTestParameter) { @Test fun wallpaperLayerIsNeverVisible() { testSpec.assertLayers { - this.isInvisible(WALLPAPER) + this.isInvisible(mWallpaper) this.isInvisible(WALLPAPER_BBQ_WRAPPER) } } @@ -229,15 +233,14 @@ class TaskTransitionTest(val testSpec: FlickerTestParameter) { fun statusBarLayerIsVisible() = testSpec.statusBarLayerIsVisible() companion object { - private val WALLPAPER = getWallpaperPackage(InstrumentationRegistry.getInstrumentation()) private val LAUNCH_NEW_TASK_ACTIVITY = LAUNCH_NEW_TASK_ACTIVITY_COMPONENT_NAME.toFlickerComponent() private val SIMPLE_ACTIVITY = SIMPLE_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME.toFlickerComponent() - private fun getWallpaperPackage(instrumentation: Instrumentation): FlickerComponentName { + private fun getWallpaperPackage(instrumentation: Instrumentation): FlickerComponentName? { val wallpaperManager = WallpaperManager.getInstance(instrumentation.targetContext) - return wallpaperManager.wallpaperInfo.component.toFlickerComponent() + return wallpaperManager.wallpaperInfo?.component?.toFlickerComponent() } @Parameterized.Parameters(name = "{0}") diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt index 8b851e5cfc2b..f0d16f3edb11 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt @@ -25,13 +25,11 @@ import com.android.server.wm.flicker.FlickerTestParameterFactory import com.android.server.wm.flicker.annotation.Group3 import com.android.server.wm.flicker.dsl.FlickerBuilder import com.android.server.wm.flicker.helpers.SimpleAppHelper -import com.android.server.wm.flicker.rules.WMFlickerServiceRuleForTestSpec import com.android.server.wm.flicker.statusBarLayerIsVisible import com.android.server.wm.flicker.statusBarLayerRotatesScales import com.android.server.wm.flicker.statusBarWindowIsVisible import com.android.server.wm.traces.common.FlickerComponentName import org.junit.FixMethodOrder -import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters @@ -80,9 +78,6 @@ import org.junit.runners.Parameterized class ChangeAppRotationTest( testSpec: FlickerTestParameter ) : RotationTransition(testSpec) { - @get:Rule - val flickerRule = WMFlickerServiceRuleForTestSpec(testSpec) - override val testApp = SimpleAppHelper(instrumentation) override val transition: FlickerBuilder.() -> Unit get() = { diff --git a/tests/componentalias/src/android/content/componentalias/tests/BaseComponentAliasTest.java b/tests/componentalias/src/android/content/componentalias/tests/BaseComponentAliasTest.java index 164f61c4c630..99322ee46106 100644 --- a/tests/componentalias/src/android/content/componentalias/tests/BaseComponentAliasTest.java +++ b/tests/componentalias/src/android/content/componentalias/tests/BaseComponentAliasTest.java @@ -46,11 +46,15 @@ public class BaseComponentAliasTest { sDeviceConfig.set("enable_experimental_component_alias", ""); sDeviceConfig.set("component_alias_overrides", ""); - // Make sure the feature is actually enabled. + // Make sure the feature is actually enabled, and the aliases are loaded. TestUtils.waitUntil("Wait until component alias is actually enabled", () -> { - return ShellUtils.runShellCommand("dumpsys activity component-alias") - .indexOf("Enabled: true") > 0; + String out = ShellUtils.runShellCommand("dumpsys activity component-alias"); + + return out.contains("Enabled: true") + && out.contains("android.content.componentalias.tests/.b.Alias04") + && out.contains("android.content.componentalias.tests/.s.Alias04"); }); + ShellUtils.runShellCommand("am wait-for-broadcast-idle"); } @AfterClass diff --git a/tests/utils/hostutils/src/com/android/internal/util/test/SystemPreparer.java b/tests/utils/hostutils/src/com/android/internal/util/test/SystemPreparer.java index 525a78486efc..c25ce71207ae 100644 --- a/tests/utils/hostutils/src/com/android/internal/util/test/SystemPreparer.java +++ b/tests/utils/hostutils/src/com/android/internal/util/test/SystemPreparer.java @@ -21,7 +21,6 @@ import static org.junit.Assert.assertTrue; import com.android.tradefed.device.DeviceNotAvailableException; import com.android.tradefed.device.ITestDevice; -import com.android.tradefed.log.LogUtil; import org.junit.Assert; import org.junit.ClassRule; @@ -369,7 +368,9 @@ public class SystemPreparer extends ExternalResource { device.executeShellCommand("disable-verity"); device.reboot(); } - device.executeShellCommand("remount"); + device.enableAdbRoot(); + device.remountSystemWritable(); + device.remountVendorWritable(); device.waitForDeviceAvailable(); } diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java index bb98bc0bab53..54b3c400af4f 100644 --- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java +++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java @@ -65,6 +65,7 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.net.TelephonyNetworkSpecifier; +import android.net.Uri; import android.net.vcn.IVcnStatusCallback; import android.net.vcn.IVcnUnderlyingNetworkPolicyListener; import android.net.vcn.VcnConfig; @@ -114,18 +115,24 @@ import java.util.UUID; public class VcnManagementServiceTest { private static final String TEST_PACKAGE_NAME = VcnManagementServiceTest.class.getPackage().getName(); + private static final String TEST_PACKAGE_NAME_2 = "TEST_PKG_2"; private static final String TEST_CB_PACKAGE_NAME = VcnManagementServiceTest.class.getPackage().getName() + ".callback"; private static final ParcelUuid TEST_UUID_1 = new ParcelUuid(new UUID(0, 0)); private static final ParcelUuid TEST_UUID_2 = new ParcelUuid(new UUID(1, 1)); + private static final ParcelUuid TEST_UUID_3 = new ParcelUuid(new UUID(2, 2)); private static final VcnConfig TEST_VCN_CONFIG; + private static final VcnConfig TEST_VCN_CONFIG_PKG_2; private static final int TEST_UID = Process.FIRST_APPLICATION_UID; static { final Context mockConfigContext = mock(Context.class); - doReturn(TEST_PACKAGE_NAME).when(mockConfigContext).getOpPackageName(); + doReturn(TEST_PACKAGE_NAME).when(mockConfigContext).getOpPackageName(); TEST_VCN_CONFIG = VcnConfigTest.buildTestConfig(mockConfigContext); + + doReturn(TEST_PACKAGE_NAME_2).when(mockConfigContext).getOpPackageName(); + TEST_VCN_CONFIG_PKG_2 = VcnConfigTest.buildTestConfig(mockConfigContext); } private static final Map<ParcelUuid, VcnConfig> TEST_VCN_CONFIG_MAP = @@ -246,18 +253,24 @@ public class VcnManagementServiceTest { eq(android.Manifest.permission.NETWORK_FACTORY), any()); } + private void setupMockedCarrierPrivilege(boolean isPrivileged) { + setupMockedCarrierPrivilege(isPrivileged, TEST_PACKAGE_NAME); + } + + private void setupMockedCarrierPrivilege(boolean isPrivileged, String pkg) { doReturn(Collections.singletonList(TEST_SUBSCRIPTION_INFO)) .when(mSubMgr) .getSubscriptionsInGroup(any()); doReturn(mTelMgr) .when(mTelMgr) .createForSubscriptionId(eq(TEST_SUBSCRIPTION_INFO.getSubscriptionId())); - doReturn(isPrivileged - ? CARRIER_PRIVILEGE_STATUS_HAS_ACCESS - : CARRIER_PRIVILEGE_STATUS_NO_ACCESS) + doReturn( + isPrivileged + ? CARRIER_PRIVILEGE_STATUS_HAS_ACCESS + : CARRIER_PRIVILEGE_STATUS_NO_ACCESS) .when(mTelMgr) - .checkCarrierPrivilegesForPackage(eq(TEST_PACKAGE_NAME)); + .checkCarrierPrivilegesForPackage(eq(pkg)); } @Test @@ -414,7 +427,13 @@ public class VcnManagementServiceTest { private BroadcastReceiver getPackageChangeReceiver() { final ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mMockContext).registerReceiver(captor.capture(), any(), any(), any()); + verify(mMockContext).registerReceiver(captor.capture(), argThat(filter -> { + return filter.hasAction(Intent.ACTION_PACKAGE_ADDED) + && filter.hasAction(Intent.ACTION_PACKAGE_REPLACED) + && filter.hasAction(Intent.ACTION_PACKAGE_REMOVED) + && filter.hasAction(Intent.ACTION_PACKAGE_DATA_CLEARED) + && filter.hasAction(Intent.ACTION_PACKAGE_FULLY_REMOVED); + }), any(), any()); return captor.getValue(); } @@ -539,6 +558,44 @@ public class VcnManagementServiceTest { } @Test + public void testPackageChangeListener_packageDataCleared() throws Exception { + triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_1, Collections.singleton(TEST_UUID_1)); + final Vcn vcn = mVcnMgmtSvc.getAllVcns().get(TEST_UUID_1); + + final BroadcastReceiver receiver = getPackageChangeReceiver(); + assertEquals(TEST_VCN_CONFIG_MAP, mVcnMgmtSvc.getConfigs()); + + final Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED); + intent.setData(Uri.parse("package:" + TEST_PACKAGE_NAME)); + intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(TEST_UID)); + + receiver.onReceive(mMockContext, intent); + mTestLooper.dispatchAll(); + verify(vcn).teardownAsynchronously(); + assertTrue(mVcnMgmtSvc.getConfigs().isEmpty()); + verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class)); + } + + @Test + public void testPackageChangeListener_packageFullyRemoved() throws Exception { + triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_1, Collections.singleton(TEST_UUID_1)); + final Vcn vcn = mVcnMgmtSvc.getAllVcns().get(TEST_UUID_1); + + final BroadcastReceiver receiver = getPackageChangeReceiver(); + assertEquals(TEST_VCN_CONFIG_MAP, mVcnMgmtSvc.getConfigs()); + + final Intent intent = new Intent(Intent.ACTION_PACKAGE_FULLY_REMOVED); + intent.setData(Uri.parse("package:" + TEST_PACKAGE_NAME)); + intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(TEST_UID)); + + receiver.onReceive(mMockContext, intent); + mTestLooper.dispatchAll(); + verify(vcn).teardownAsynchronously(); + assertTrue(mVcnMgmtSvc.getConfigs().isEmpty()); + verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class)); + } + + @Test public void testSetVcnConfigRequiresNonSystemServer() throws Exception { doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid(); @@ -578,7 +635,7 @@ public class VcnManagementServiceTest { @Test public void testSetVcnConfigMismatchedPackages() throws Exception { try { - mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, TEST_VCN_CONFIG, "IncorrectPackage"); + mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, TEST_VCN_CONFIG, TEST_PACKAGE_NAME_2); fail("Expected exception due to mismatched packages in config and method call"); } catch (IllegalArgumentException expected) { verify(mMockPolicyListener, never()).onPolicyChanged(); @@ -678,11 +735,12 @@ public class VcnManagementServiceTest { } @Test - public void testClearVcnConfigRequiresCarrierPrivileges() throws Exception { + public void testClearVcnConfigRequiresCarrierPrivilegesOrProvisioningPackage() + throws Exception { setupMockedCarrierPrivilege(false); try { - mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME); + mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME_2); fail("Expected security exception for missing carrier privileges"); } catch (SecurityException expected) { } @@ -691,20 +749,32 @@ public class VcnManagementServiceTest { @Test public void testClearVcnConfigMismatchedPackages() throws Exception { try { - mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, "IncorrectPackage"); + mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME_2); fail("Expected security exception due to mismatched packages"); } catch (SecurityException expected) { } } @Test - public void testClearVcnConfig() throws Exception { + public void testClearVcnConfig_callerIsProvisioningPackage() throws Exception { + // Lose carrier privileges to test that provisioning package is sufficient. + setupMockedCarrierPrivilege(false); + mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME); assertTrue(mVcnMgmtSvc.getConfigs().isEmpty()); verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class)); } @Test + public void testClearVcnConfig_callerIsCarrierPrivileged() throws Exception { + setupMockedCarrierPrivilege(true, TEST_PACKAGE_NAME_2); + + mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME_2); + assertTrue(mVcnMgmtSvc.getConfigs().isEmpty()); + verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class)); + } + + @Test public void testClearVcnConfigNotifiesStatusCallback() throws Exception { setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_2, true /* isActive */); mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_2, mMockStatusCallback, TEST_PACKAGE_NAME); @@ -755,11 +825,12 @@ public class VcnManagementServiceTest { @Test public void testGetConfiguredSubscriptionGroupsMismatchedPackages() throws Exception { - final String badPackage = "IncorrectPackage"; - doThrow(new SecurityException()).when(mAppOpsMgr).checkPackage(TEST_UID, badPackage); + doThrow(new SecurityException()) + .when(mAppOpsMgr) + .checkPackage(TEST_UID, TEST_PACKAGE_NAME_2); try { - mVcnMgmtSvc.getConfiguredSubscriptionGroups(badPackage); + mVcnMgmtSvc.getConfiguredSubscriptionGroups(TEST_PACKAGE_NAME_2); fail("Expected security exception due to mismatched packages"); } catch (SecurityException expected) { } @@ -767,14 +838,16 @@ public class VcnManagementServiceTest { @Test public void testGetConfiguredSubscriptionGroups() throws Exception { + setupMockedCarrierPrivilege(true, TEST_PACKAGE_NAME_2); mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); + mVcnMgmtSvc.setVcnConfig(TEST_UUID_3, TEST_VCN_CONFIG_PKG_2, TEST_PACKAGE_NAME_2); - // Assert that if both UUID 1 and 2 are provisioned, the caller only gets ones that they are - // privileged for. + // Assert that if UUIDs 1, 2 and 3 are provisioned, the caller only gets ones that they are + // privileged for, or are the provisioning package of. triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_1, Collections.singleton(TEST_UUID_1)); final List<ParcelUuid> subGrps = mVcnMgmtSvc.getConfiguredSubscriptionGroups(TEST_PACKAGE_NAME); - assertEquals(Collections.singletonList(TEST_UUID_1), subGrps); + assertEquals(Arrays.asList(new ParcelUuid[] {TEST_UUID_1, TEST_UUID_2}), subGrps); } @Test diff --git a/tools/aapt/SdkConstants.h b/tools/aapt/SdkConstants.h index f57c4ee9d5b6..a146466402f6 100644 --- a/tools/aapt/SdkConstants.h +++ b/tools/aapt/SdkConstants.h @@ -48,6 +48,7 @@ enum { SDK_R = 30, SDK_S = 31, SDK_S_V2 = 32, + SDK_TIRAMISU = 33, SDK_CUR_DEVELOPMENT = 10000, }; diff --git a/tools/aapt2/SdkConstants.h b/tools/aapt2/SdkConstants.h index f2aaaf5ddcf0..0bd61c04f2b2 100644 --- a/tools/aapt2/SdkConstants.h +++ b/tools/aapt2/SdkConstants.h @@ -58,6 +58,7 @@ enum : ApiVersion { SDK_R = 30, SDK_S = 31, SDK_S_V2 = 32, + SDK_TIRAMISU = 33, SDK_CUR_DEVELOPMENT = 10000, }; diff --git a/tools/apilint/deprecated_at_birth.py b/tools/apilint/deprecated_at_birth.py index 297d9c3bcca0..d53c12734d23 100644..100755 --- a/tools/apilint/deprecated_at_birth.py +++ b/tools/apilint/deprecated_at_birth.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright (C) 2021 The Android Open Source Project # @@ -44,6 +44,7 @@ def ident(raw): can be used to identify members across API levels.""" raw = raw.replace(" deprecated ", " ") raw = raw.replace(" synchronized ", " ") + raw = raw.replace(" abstract ", " ") raw = raw.replace(" final ", " ") raw = re.sub("<.+?>", "", raw) raw = re.sub("@[A-Za-z]+ ", "", raw) @@ -208,17 +209,17 @@ def _parse_stream(f, api={}): def _parse_stream_path(path): api = {} - print "Parsing", path + print("Parsing %s" % path) for f in os.listdir(path): f = os.path.join(path, f) if not os.path.isfile(f): continue if not f.endswith(".txt"): continue if f.endswith("removed.txt"): continue - print "\t", f + print("\t%s" % f) with open(f) as s: api = _parse_stream(s, api) - print "Parsed", len(api), "APIs" - print + print("Parsed %d APIs" % len(api)) + print() return api @@ -306,8 +307,8 @@ if __name__ == "__main__": if "@Deprecated " in i.raw: error(clazz, i, None, "Found API deprecation at birth " + i.ident) - print "%s Deprecated at birth %s\n" % ((format(fg=WHITE, bg=BLUE, bold=True), - format(reset=True))) + print("%s Deprecated at birth %s\n" % ((format(fg=WHITE, bg=BLUE, bold=True), + format(reset=True)))) for f in sorted(failures): - print failures[f] - print + print(failures[f]) + print() |